Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
478 views
in Technique[技术] by (71.8m points)

c# - Stubbing or Mocking ASP.NET Web API HttpClient

I am using the new Web API bits in a project, and I have found that I cannot use the normal HttpMessageRequest, as I need to add client certificates to the request. As a result, I am using the HttpClient (so I can use WebRequestHandler). This all works well, except that it isn't stub/mock friendly, at least for Rhino Mocks.

I would normally create a wrapper service around HttpClient that I would use instead, but I would like to avoid this if possible, as there are a lot of methods that I would need to wrap. I am hoping that I have missing something—any suggestions on how to stub HttpClient?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As an alternative to the excellent ideas already presented by @Raj, it may be possible to go a step lower and to mock/fake the HttpMessageHandler instead.

If you make any class that needs an HttpClient accept it as a dependency injection parameter in the constructor, then when unit testing you can pass in an HttpClient that has been injected with your own HttpMessageHandler. This simple class has only one abstract method that you need to implement, as follows:

public class FakeHttpMessageHandler : HttpMessageHandler
    {
    public HttpRequestMessage RequestMessage { get; private set; }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
        RequestMessage = request;
        return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
        }
    }

My trivial example just saves the HttpRequestMessage in a public property for later inspection and returns HTTP 200 (OK), but you could augment this by adding a constructor that sets the result you want returned.

You'd use this class like this:

public void foo()
    {
    //Arrange
    var fakeHandler = new FakeHttpMessageHandler();
    var client = new HttpClient(fakeHandler);
    var SUT = new ClassUnderTest(client);

    //Act
    SUT.DomSomething();

    //Assert
    fakeHandler.RequestMessage.Method.ShouldEqual(HttpMethod.Get); // etc...
    }

There are limitations to this approach, for example in a method that makes multiple requests or needs to create multiple HttpClients, then the fake handler might start to become too complicated. However, it may be worth consideration for simple cases.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...