0

如何模拟代理服务器的功能/操作,但不调用 HttpListener 或 TcpListener 等元素?如何从我的 C# 应用程序中生成它们?

我已经能够将实际数据流式传输回我的 C# 应用程序中的 WebBrowser 元素,但是在查看结果时,它给了我错误。原因是因为我正在查看 LITERAL 字符串,并且生成的 HTML 流中有 JS/CSS 组件通过相对 URI 引用对象。显然,我的解决方案认为它们是本地的,因此无法解决它们。

我缺少类似代理的功能,它应该只是将流传递回我的模拟浏览器并正确显示。但是,查看基于 C# 构建的示例代理服务器代码,它们都是使用侦听器构建为服务器的。我希望它是我可以在本地实例化而无需创建监听接口的东西。

现在,您可能想知道我为什么要这样做?嗯,有几个原因:

  • 为了能够临时注入标头,以便我可以测试内部 Web 服务器
  • 作为一个无头(无 GUI)组件运行,该组件可以从其他 .NET 组件获取 HTTP 或 HTTPS 流,并从其他 .NET 组件注入标头。
  • 其他一些我认为可能但在我把它准备好之前不会知道的后端东西。

这是我到目前为止所拥有的:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using HtmlAgilityPack;
using System.Net;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            WebClient client = new WebClient();
            var baseUrl = new Uri(textBox1.Text);
            client.Headers.Add("Token1", textBox2.Text);
            client.Headers.Add("Token2",textBox3.Text);

            byte[] requestHTML = client.DownloadData(textBox1.Text);
            string sourceHTML = new UTF8Encoding().GetString(requestHTML);

            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.LoadHtml(sourceHTML);

            //"//*[@background or @lowsrc or @src or @href]"    
            foreach (HtmlNode link in htmlDoc.DocumentNode.SelectNodes("//*[@href]"))
            {
                //Console.Out.WriteLine(link.ToString());
                if (!string.IsNullOrEmpty(link.Attributes["href"].Value))
                {
                    HtmlAttribute att = link.Attributes["href"];
                    Console.WriteLine("Before: " + att.Value);
                    //Console.Out.WriteLine(att.Value.ToString());
                    Console.WriteLine(new Uri(baseUrl, att.Value));
                    link.Attributes["href"].Value = new Uri(baseUrl, att.Value).ToString();
                    Console.WriteLine("After: " + link.Attributes["href"].Value);

                    //att.Value = this.AbsoluteUrlByRelative(att.Value);
                }
            }

            foreach (HtmlNode link2 in htmlDoc.DocumentNode.SelectNodes("//*[@src]"))
            {
                //Console.Out.WriteLine(link.ToString());
                if (!string.IsNullOrEmpty(link2.Attributes["src"].Value))
                {
                    HtmlAttribute att = link2.Attributes["src"];
                    Console.WriteLine("Before: " + att.Value);
                //    //Console.Out.WriteLine(att.Value.ToString());
                    Console.WriteLine(new Uri(baseUrl, att.Value));
                    if (!att.Value.Contains("/WS"))
                    {
                        Console.WriteLine("HIT ME!");
                        var output = "/WS/" + att.Value;
                        link2.Attributes["src"].Value = new Uri(baseUrl, output).ToString();
                        Console.WriteLine("After HIT: " + link2.Attributes["src"].Value);
                    }
                    else
                    {
                        link2.Attributes["src"].Value = new Uri(baseUrl, att.Value).ToString();
                        Console.WriteLine("After: " + link2.Attributes["src"].Value);
                    }


                //    //att.Value = this.AbsoluteUrlByRelative(att.Value);
                }
            }

            Console.WriteLine(htmlDoc.DocumentNode.OuterHtml);
            Console.WriteLine("+========================+");
            webBrowser1.DocumentText = htmlDoc.DocumentNode.OuterHtml;

        }
    }
}

同样,这只是原型代码,所以请原谅古怪的间距和注释。最后,它会更正式。现在,这只猴子正在杀死我。

4

1 回答 1

0

NMock使用类似或类似的东西怎么样?这意味着必须引入接口以便可以注入模拟,但仍然比几乎任何其他方式都要好,恕我直言......

从 NMock 网站:

NMock 是一个用于 .NET 的动态模拟对象库。模拟对象使测试单个组件(通常是单个类)变得更容易,而无需依赖所有其他组件的实际实现。这意味着我们可以只测试一个类,而不是整个对象树,并且可以更清楚地查明错误。在测试驱动开发期间经常使用模拟对象。

您或多或少会像这样模拟代理服务器:

var mocks = new Mockery();
var mockProxyServer = mocks.NewMock<IMyProxyServer>();

这就是你需要做的。如您所见,它依赖于接口。但通常我需要做的就是重构->从 VS 中的相关类中提取接口。

设置模拟通常在单元测试的上下文中完成,例如:

public class TransferFundsPresenterTest
{
    private Mockery mocks;
    private IMyProxyServer mockProxyServer

    [SetUp]
    public void SetUp()
    {
        mocks = new Mockery();
        mockProxyServer = mocks.NewMock<IMyProxyServer>();
    }

    [Test]
    public void TestProxyFunction()
    {
        Expect.Once.On(mockProxyServer).
            Method("ProxyFunctionA").
            With("1234").   //  <-- simulate the input params here
            Will(Return.Value("Test"));  // <-- simulate the output from server here
    }

这只是一个基本的例子。你可以做更多,这是一个非常灵活的库。

你真的应该看看这个NMock网站,它很容易完全跟上图书馆的速度。

http://www.nmock.org/index.html

于 2012-08-24T02:52:04.053 回答