简体   繁体   English

单元测试库中的WebRequest.CreateHttp

[英]Unit testing WebRequest.CreateHttp within a library

My scenario is this -- I have a concrete class (RestSupport) behind an interface (IRestSupport) that has two core methods: CreateRequest and GetResponse. 我的情况是这样的 - 我在接口(IRestSupport)后面有一个具体的类(RestSupport),它有两个核心方法:CreateRequest和GetResponse。 This class is designed to allow me to talk to web endpoints via JSON. 此类旨在允许我通过JSON与Web端点进行通信。 This class gets called by another class that has the higher level business logic to provide the exact JSON that needs to be sent. 此类由另一个具有更高级别业务逻辑的类调用,以提供需要发送的确切JSON。

I need to be able to unit test those two methods such that they don't call the endpoints during testing. 我需要能够对这两种方法进行单元测试,以便它们在测试期间不会调用端点。 CreateRequest relies on HttpWebRequest because I need to add information to the Headers collection. CreateRequest依赖于HttpWebRequest,因为我需要向Headers集合添加信息。 There is more code than this, but below gives you an example. 代码多于此,但下面给出了一个示例。

var request = WebRequest.Create(url) as HttpWebRequest;
request.Headers.Add("Authorization", AuthorizationHeader);

I see many examples on the web of using IWebRequestCreate such that you can control the request creation. 我在Web上看到许多使用IWebRequestCreate的示例,以便您可以控制请求创建。 The problem that I'm having is that I cannot seem to get this to work properly when using HttpWebRequest. 我遇到的问题是,在使用HttpWebRequest时,我似乎无法正常工作。 The Create method of IWebRequestCreate expects that you will return a WebRequest object. IWebRequestCreate的Create方法期望您将返回WebRequest对象。 The downside of the web examples is that they're not using HttpWebRequest. Web示例的缺点是它们没有使用HttpWebRequest。 I cannot derive a class from HttpWebRequest, which is really the crux of my problem. 我无法从HttpWebRequest派生出一个类,这实际上是我问题的症结所在。

I do not have access to fakes, but can use Moq. 我无法获得假货,但可以使用Moq。 My goal is to not modify the library code if it can be avoided. 我的目标是在可以避免的情况下不修改库代码。

I suppose you are talking about unit test in memory. 我想你在谈论内存中的单元测试。 The simplest way is to "hide" these two lines in another class that implements an interface. 最简单的方法是在另一个实现接口的类中“隐藏”这两行。 Now you can mock the interface. 现在你可以模拟界面了。 It is sound strange to me that you have just those 2 lines... I guess there are more un-testable things in your class. 我觉得你只有那两行......我觉得你班上还有更多不可测试的东西。 My suggestion is to separate all the logic that you want to test to some "infrastructure" details that do not worth to test. 我的建议是将您要测试的所有逻辑分离为一些不值得测试的“基础架构”细节。

I had exactly the same problem yesterday, and this is how I fixed it. 昨天我遇到了完全相同的问题,这就是我修复它的方法。

The class that contains the WebRequest takes a IWebRequestCreate in the constructor. 包含WebRequestIWebRequestCreate在构造函数中使用IWebRequestCreate

class MyClass
{
    IWebRequestCreate _web;
    public MyClass(IWebRequestCreate web)
    {
       _web = web;
    }
    public void Download(string url)
    {
       var request = _web.Create(url);

    }
}

In the application, I register my class with the IoC container: 在应用程序中,我使用IoC容器注册我的类:

class MyWebRequest : IWebRequestCreate
{
    public WebRequest Create(Uri uri)
    {
        return WebRequest.Create(uri);
    }
}

In my tests I create a mock with the functions I need overwritten: 在我的测试中,我创建了一个模拟我需要覆盖的函数:

void TestSetupMocks()
{
    var request = new TestWebRequest();
    Mock<IWebRequestCreate> _webClientFactory;
    _webClientFactory.Setup(x => x.Create(uri)).Returns(request);
}

class TestWebRequest : WebRequest
{
   // Implement abstract functions
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM