简体   繁体   中英

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. This class is designed to allow me to talk to web endpoints via JSON. This class gets called by another class that has the higher level business logic to provide the exact JSON that needs to be sent.

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. 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. The problem that I'm having is that I cannot seem to get this to work properly when using HttpWebRequest. The Create method of IWebRequestCreate expects that you will return a WebRequest object. The downside of the web examples is that they're not using HttpWebRequest. I cannot derive a class from HttpWebRequest, which is really the crux of my problem.

I do not have access to fakes, but can use 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.

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:

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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