使用Moq模拟HttpClient

编程入门 行业动态 更新时间:2024-10-23 13:38:57
本文介绍了使用Moq模拟HttpClient的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我喜欢对使用HttpClient的类进行单元测试.我们将HttpClient对象注入到类构造函数中.

I like to unit test a class that use HttpClient. We injected the HttpClient object in the class constructor.

public class ClassA : IClassA { private readonly HttpClient _httpClient; public ClassA(HttpClient httpClient) { _httpClient = httpClient; } public async Task<HttpResponseMessage> SendRequest(SomeObject someObject) { //Do some stuff var request = new HttpRequestMessage(HttpMethod.Post, "some-domain.in"); //Build the request var response = await _httpClient.SendAsync(request); return response; } }

现在,我们想对ClassA.SendRequest方法进行单元测试.我们将Ms Test用于单元测试框架,并将Moq用于模拟.

Now we like to unit test the ClassA.SendRequest method. We are using Ms Test for unit testing framework and Moq for mocking.

当我们尝试模拟HttpClient时,它会抛出NotSupportedException.

When we tried to mock the HttpClient, it throws NotSupportedException.

[TestMethod] public async Task SendRequestAsync_Test() { var mockHttpClient = new Mock<HttpClient>(); mockHttpClient.Setup( m => m.SendAsync(It.IsAny<HttpRequestMessage>())) .Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); }

我们如何解决这个问题?

How can we solve this issue?

推荐答案

该特定的重载方法不是虚拟的,因此无法被Moq覆盖.

That particular overload method is not virtual so is unable to be overridden by Moq.

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);

这就是为什么它抛出NotSupportedException

您正在寻找的虚拟方法就是这种方法

The virtual method you are looking for is this method

public virtual Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);

但是模拟HttpClient并不像使用其内部消息处理程序那样简单.

However mocking HttpClient is not as simple as it seems with its internal message handler.

我建议使用带有自定义消息处理程序存根的具体客户端,以便在伪造请求时提供更大的灵活性.

I suggest using a concrete client with a custom message handler stub that will allow for more flexibility when faking the request.

这里是委派处理程序存根的示例.

Here is an example of a delegating handler stub.

public class DelegatingHandlerStub : DelegatingHandler { private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> _handlerFunc; public DelegatingHandlerStub() { _handlerFunc = (request, cancellationToken) => Task.FromResult(request.CreateResponse(HttpStatusCode.OK)); } public DelegatingHandlerStub(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> handlerFunc) { _handlerFunc = handlerFunc; } protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return _handlerFunc(request, cancellationToken); } }

请注意,默认构造函数基本上是在做您以前尝试模仿的事情.它还允许带有请求委托的更多自定义方案.

Note the default constructor is doing basically what you were trying to mock before. It also allows for more custom scenarios with a delegate for the request.

使用存根,可以将测试重构为类似的内容

With the stub, the test can be refactored to something like

public async Task _SendRequestAsync_Test() { //Arrange var handlerStub = new DelegatingHandlerStub(); var client = new HttpClient(handlerStub); var sut = new ClassA(client); var obj = new SomeObject() { //Populate }; //Act var response = await sut.SendRequest(obj); //Assert Assert.IsNotNull(response); Assert.IsTrue(response.IsSuccessStatusCode); }

更多推荐

使用Moq模拟HttpClient

本文发布于:2023-10-31 07:40:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1545463.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Moq   HttpClient

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!