【问题标题】:Mocked HttpClient wrapper returning null with xunit使用 xunit 返回 null 的模拟 HttpClient 包装器
【发布时间】:2017-04-06 09:32:57
【问题描述】:

我正在尝试习惯使用 .net 核心进行单元测试。不幸的是,我一直坚持让我的 HttpClient 包装器返回失败的 HttpResponseMessage

这是我正在尝试进行的测试:

[Fact]
public async void TestHttpExceptionOnBadRequest()
{
    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("Test")))
    {
        var xmlSerializer = new Mock<IXmlSerializer>();
        xmlSerializer.Setup(serializer => serializer.Deserialize(stream)).Returns(new object());

        var httpClient = new Mock<IHttpHandler>();
        httpClient.Setup(client => client.GetAsync("Test"))
            .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));

        var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
        await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
    }
}

以下是我的服务代码。问题是 response.EnsureSuccessStatusCode(); 返回 null。

public async Task<PostcodeContainer> SearchAsync(string text, string container)
{
    // add the query parameters to the query string
    var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
    query += "&container=" + WebUtility.UrlEncode(container);

    // initiate client & response
    var response = await _httpClient.GetAsync(query);
    response.EnsureSuccessStatusCode();

    return (PostcodeContainer)_serializer.Deserialize(await response.Content.ReadAsStreamAsync());
}

为了完整起见,这里是我的 IHttpHandler 定义,用于模拟。

public interface IHttpHandler
{
    HttpResponseMessage Get(string url);
    HttpResponseMessage Post(string url, HttpContent content);
    Task<HttpResponseMessage> GetAsync(string url);
    Task<HttpResponseMessage> PostAsync(string url, HttpContent content);
}

【问题讨论】:

    标签: c# .net unit-testing moq xunit


    【解决方案1】:

    这是因为预期的查询设置与被测方法中生成的不匹配。

    // add the query parameters to the query string
    var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
    query += "&container=" + WebUtility.UrlEncode(container);
    

    这会导致模拟返回null,因为它在收到与"Test" 不匹配的意外查询时不知道该怎么做。

    所以假设 _baseQueryString 也是一个空字符串,基于示例中的测试,生成的查询可能会结束

    &text=&container=
    

    因此,为了按预期执行,这是模拟应该期望接收的。还考虑到在序列化程序执行任何操作之前,被测方法预计会出错,因此无需设置它来执行任何操作。只需模拟它并通过模拟。

    您还可以通过在设置表达式中使用It.IsAny&lt;string&gt;() 让客户端期待任何查询。

    最后,如果执行 acync 函数,让测试返回 Task

    [Fact]
    public async Task TestHttpExceptionOnBadRequest() {
    
        var xmlSerializer = new Mock<IXmlSerializer>();
        xmlSerializer
            .Setup(serializer => serializer.Deserialize(It.IsAny<Stream>()))
            .Returns(new PostcodeContainer());
    
        var expectedResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);
        var httpClient = new Mock<IHttpHandler>();
        httpClient
            .Setup(client => client.GetAsync(It.IsAny<string>()))
            .ReturnsAsync(expectedResponse);
    
        var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
        await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-01
      • 2021-05-29
      • 2020-04-29
      • 2019-09-27
      • 2021-12-24
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多