我们的代码中有时候会需要调用其他平台的接口,在做单元测试的时候,我们不需要测试这些第三方接口是否生效,接口是否有问题,但是如果我们直接调用第三方接口,这些接口的错误又会影响我们正常的测试工作,所以我们应该怎么办呢?我们可以模拟这些接口,让其返回我们期待的返回结果,这样我们就可以顺利的进行内部代码的测试了。
这里我们继承HttpMessageHandler
,写一个MockHttpMessageHandler
。
public class MockHttpMessageHandler : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(MockSend(request, cancellationToken));
}
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
{
return MockSend(request, cancellationToken);
}
public virtual HttpResponseMessage MockSend(HttpRequestMessage request, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
然后我们通过Substitute.ForPartsOf<T>()
方法创建一个MockHttpMessageHandler
对象,将其传参给HttpClient
对象。
var mockHttpMessageHandler = Substitute.ForPartsOf<MockHttpMessageHandler>();
httpClient = new HttpClient(mockHttpMessageHandler);
然后通过Nsubstitute
的Return
等方法设置返回结果HttpResponseMessage
。
HttpResponseMessage mockResponse = new HttpResponseMessage(HttpStatusCode.OK);
mockResponse.Content = new StringContent(returnMessage);
mockHttpMessageHandler.MockSend(Arg.Any<HttpRequestMessage>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(mockResponse);
这里我们设置任意参数的MockSend
方法均返回HttpStatusCode=OK,返回值为returnMessage。
在实际测试过程中,我们可以根据具体的情况返回不同的结果。
整段测试代码如下:
public class MockHttpClientUnitTest
{
HttpClient httpClient;
const string returnMessage = "Ok";
public MockHttpClientUnitTest()
{
var mockHttpMessageHandler = Substitute.ForPartsOf<MockHttpMessageHandler>();
httpClient = new HttpClient(mockHttpMessageHandler);
//mock response
HttpResponseMessage mockResponse = new HttpResponseMessage(HttpStatusCode.OK);
mockResponse.Content = new StringContent(returnMessage);
mockHttpMessageHandler.MockSend(Arg.Any<HttpRequestMessage>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(mockResponse);
}
[Fact]
public async void Test()
{
(await (await httpClient.GetAsync("https://cn.bing.com/")).Content.ReadAsStringAsync()).ShouldBe(returnMessage);
}
}
示例代码
MockHttpClientUnitTestMockHttpMessageHandler
参考资料
Partial subs and test spiesHow to Mock HttpClient using NSubstitute
学习技术最好的文档就是【官方文档】,没有之一。
还有学习资料【Microsoft Learn】、【CSharp Learn】、【My Note】。
如果,你希望更容易地发现我的新博客,不妨点击一下【关注】。