当前位置: 首页 > 知识库问答 >
问题:

如何在.NET Core2.1中使用Moq模拟新的HttpClientFactory

高寒
2023-03-14

使用。NET核心IoC容器注入工厂,该方法所做的是从工厂创建一个新客户机:

var client = _httpClientFactory.CreateClient();

然后使用客户机从REST服务获取数据:

var result = await client.GetStringAsync(url);

共有1个答案

端木兴国
2023-03-14

HttpClientFactory派生自IHttpClientFactory接口,因此只需创建接口的模拟

var mockFactory = new Mock<IHttpClientFactory>();

根据客户机的用途,您需要设置模拟以返回HttpClient用于测试

但是,这需要一个实际的HttpClient

var clientHandlerStub = new DelegatingHandlerStub();
var client = new HttpClient(clientHandlerStub);

mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);

IHttpClientFactory factory = mockFactory.Object;

然后,在执行测试时,工厂可以被注入到被测试的依赖系统中。

如果不希望客户端调用实际的endpoint,则需要创建一个假的委托处理程序来拦截请求。

用于伪造请求的处理程序存根示例

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);
    }
}
[Route("api/[controller]")]
public class ValuesController : Controller {
    private readonly IHttpClientFactory _httpClientFactory;

    public ValuesController(IHttpClientFactory httpClientFactory) {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet]
    public async Task<IActionResult> Get() {
        var client = _httpClientFactory.CreateClient();
        var url = "http://example.com";
        var result = await client.GetStringAsync(url);
        return Ok(result);
    }
}
public async Task Should_Return_Ok() {
    //Arrange
    var expected = "Hello World";
    var mockFactory = new Mock<IHttpClientFactory>();
    var configuration = new HttpConfiguration();
    var clientHandlerStub = new DelegatingHandlerStub((request, cancellationToken) => {
        request.SetConfiguration(configuration);
        var response = request.CreateResponse(HttpStatusCode.OK, expected);
        return Task.FromResult(response);
    });
    var client = new HttpClient(clientHandlerStub);
    
    mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);
    
    IHttpClientFactory factory = mockFactory.Object;
    
    var controller = new ValuesController(factory);
    
    //Act
    var result = await controller.Get();
    
    //Assert
    result.Should().NotBeNull();
    
    var okResult = result as OkObjectResult;
    
    var actual = (string) okResult.Value;
    
    actual.Should().Be(expected);
}
 类似资料:
  • 我试图用模拟的dbcontext为我的服务创建一个单元测试。我创建了一个接口,具有以下函数:

  • 问题内容: 我有一个使用当前时间进行一些计算的函数。我想使用模仿器模拟它。 我要测试的课程示例: 我想要类似的东西: 可以嘲笑吗?我不想更改“已测试”的代码以进行测试。 问题答案: 正确的做法是重组代码,使其更具可测试性,如下所示。重组代码以消除对Date的直接依赖关系将使您可以为正常运行时和测试运行时注入不同的实现:

  • 我知道Dan North设计BDD的意图之一是将词汇表从复杂的测试域中移开。然而,在实现由外到内的方法时,我们似乎仍然需要对模仿行为(或者,如果您愿意的话)有一些了解。North在这个视频中建议,如果我从最外层的域对象开始,然后向内工作,我会在发现合作者时模仿它们,然后用适当的实现替换它们。所以最后,我以一组端到端测试结束。 Martin Fowler在这篇博客文章中定义了TDD的两个阵营:“古典

  • 如果我错了请纠正我,但看起来Moq只能模拟一个公共类,它有一个公共的无参数构造函数,要模拟的方法是。我并不想让这些类公开可见。我是不是错过了一些与Moq的东西,或者只是不适合我想做的事情? 我想我可以创建一个ClassB实现的接口(例如“ICLASSB”),将其注入ClassA,并模拟该接口。ClassB仍然可以是内部的(尽管我意识到接口方法必须是公共的)。虽然这可以工作,但我对创建大量接口感到不

  • 我有一个jUnit测试,测试我的一个函数。在这个函数中,我调用了另一个类的方法,我想用mockito模拟这个方法。然而,我似乎不能实际嘲笑这一点。下面是我的jUnit测试的样子: 编辑:在我的MainClassImTesting()中。我正在调用的test()函数,它调用authenticateUser()并向它传递一个hashMap。

  • 出于学校目的,我正在创建一个使用股票API的应用程序。 我正在尝试为一种获取过去10年所有股票数据的方法编写一个测试。我不想实际获取所有这些数据,而是想抛出一个异常。 我想测试的方法: 股票时间系列(....)调用可以抛出阿尔法仓位异常。 我这样嘲弄了TimeSeries类: 在我的测试类中,我想模拟这个调用,并返回一个异常而不是实际数据。 无论我多么试图嘲笑这段代码,它永远不会抛出异常。它将始终