Reputation: 24308
I have created my own IHttpClient so I am able to mock HttpClient using moq. Works pretty well but there is an internal object called DetaultRequestHeaders which has a property called Authorization.
I am setting this in my constructor or my class that accepts in an injected IHttpClient, of course at runtime everything works as expected. But using Unit Tests I get an error saying
Object reference not set to instance....
This is due to the fact that the DefaultRequestHeaders is null.
Now after inverstigating this further it appears that it is of type
HttpRequestHeaders
but it's a sealed class so I can't even do this:
.Setup(x => x.DefaultRequestHeaders).Returns(return new HttpRequestHeaders())
This is the interface definition
HttpRequestHeaders DefaultRequestHeaders { get; }
Upvotes: 14
Views: 13792
Reputation: 957
Just inject the concrete HttpClient and mock the underlying HttpMessageHandler...
You can unit test a class that uses HttpClient by giving that HttpClient a mock HttpMessageHandler. This way, you can capture the request and prevent it from actually going over the wire.
Here is an example using Moq. HttpClient depends on HttpMessageHandler’s SendAsync() method, so give SendAsync() a stub implementation and use Moq’s Callback() to capture arguments.
var handler = new Mock<HttpMessageHandler>(); handler.Protected() .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>()) .Returns(Task<HttpResponseMessage>.Factory.StartNew(() => { return new HttpResponseMessage(HttpStatusCode.OK); })) .Callback<HttpRequestMessage, CancellationToken>((r, c) => { Assert.AreEqual(HttpMethod.Get, r.Method); }); using (var client = new HttpClient(handler.Object)) { var request = new HttpRequestMessage(HttpMethod.Get, "http://www.google.com"); var response = client.SendAsync(request).Result; Console.WriteLine(response.StatusCode); }
Upvotes: 17
Reputation: 1179
HttpRequestHeaders
has only internal constructor.
But you can do it by creating HttpRequestMesssage
object:
var message = new HttpRequestMessage();
.Setup(x => x.DefaultRequestHeaders).Returns(message.Headers);
Upvotes: 4
Reputation: 6683
Your syntax on the Returns
method call appears incorrect. The fact that HttpRequestHeaders
is a sealed class shouldn't have any bearing on whether you can return an instance of it from a stubbed method call. Try changing that call to Returns(new HttpRequestHeaders());
or Returns(() => new HttpRequestHeaders());
.
If that doesn't work (or the concrete implementation of HttpRequestHeaders
is somehow unsuitable for your needs), you might need to try a framework that can mock sealed classes, perhaps Moles or JustMock.
Upvotes: -2