Moq 设置 HttpClient.Send() 方法

问题描述 投票:0回答:2

我正在使用 Moq 框架用 C# 编写单元测试。我如何为以下内容编写模拟语句:

var HttpClient httpClient;

var request = new HttpRequestMessage() { ... }

httpClient.Send(request);

我已经找到了模拟 SendAsync 方法的解决方案,但不仅仅是 Send() 方法。由于我正在编写单元测试,因此我不希望我的测试向 URL 发送实际请求。

因此,我想模拟它并验证是否调用了 Send 方法。应提供什么 URL 来确保此行为,而不遇到任何其他问题?

我无法修改我的原始代码。是否可以使用 HttpMessageHandler 来执行此操作?我应该提供什么 URL 来模拟此语句,以及如何在不向 URL 发出实际请求且不会遇到其他问题(例如无效主机或无法连接到主机等)的情况下模拟此语句?谢谢你。

c# unit-testing moq
2个回答
1
投票

此方法允许您覆盖受保护的方法。 Handler 是实际进行调用的对象。如果您检查 HttpClient 发送并跟踪它,您最终会看到对 HttpMessageHandler 的调用。

[TestMethod]
public void Can_Send_HttpClient_Message()
{
    var mockedHttpMessageHandler = new Mock<HttpMessageHandler>();
    mockedHttpMessageHandler
        .Protected()
        .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage(System.Net.HttpStatusCode.OK));
    mockedHttpMessageHandler
        .Protected()
        .Setup<HttpResponseMessage>("Send", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
        .Returns(new HttpResponseMessage(System.Net.HttpStatusCode.OK));

    var httpClient = new HttpClient(mockedHttpMessageHandler.Object, false);
    var request = new HttpRequestMessage(HttpMethod.Post, "https://www.test.com");
    httpClient.Send(request);
}

在单元测试中模拟 HttpClient


0
投票

为了使代码具有良好的可扩展性和可测试性,同时也为了避免违反 SOLID 原则,我建议引入几个抽象,如下所示。该方法使用装饰器(包装器)模式,主要思想是为

HttpClient
类提供一个接口,该接口很容易注入到您的代码和模拟中。

public interface IHttpClient
{
    HttpResponseMessage Send(HttpRequestMessage request);
}

public class HttpClientWrapper : IHttpClient
{
    private readonly HttpClient _httpClient;

    public HttpClientWrapper()
    {
        _httpClient = new HttpClient();
    }

    public HttpResponseMessage Send(HttpRequestMessage request)
    {
        return _httpClient.Send(request);
    }
}

之后,在您的代码中使用类似的东西,注入

IHttpClient
:

public class MyService : IMyService
{
    private readonly IHttpClient _httpClient;

    public MyService(IHttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public void SendSomeRequest()
    {
        _httpClient.Send(new HttpRequestMessage());

        // other code goes here...
    }
}

最后,您可以像往常一样使用

IHttpClient
框架模拟这个
Moq
依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.