【问题标题】:How to mock a Stream response when calling HttpClient GetStreamAsync调用 HttpClient GetStreamAsync 时如何模拟 Stream 响应
【发布时间】:2018-05-16 19:56:53
【问题描述】:

我正在尝试测试一个使用 HttpClient 的类,我必须伪造 Stream 响应。

这是我要测试的代码。

            try
            {
                _httpClient.Timeout = TimeSpan.FromMinutes(10);
                _httpClient.BaseAddress = new Uri(BaseAddress);
                _httpClient.DefaultRequestHeaders.Accept.Clear();
                _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", _credentials);

                using (Stream s = _httpClient.GetStreamAsync(API_string).Result)  <---- this is the trouble line.
                using (StreamReader sr = new StreamReader(s))
                using (JsonReader reader = new JsonTextReader(sr))
                {
                    JsonSerializer serializer = new JsonSerializer();

                    return serializer.Deserialize<T>(reader); //breaks loop
                }
            }

从测试端,我可以插入我的自定义 HttpClientHandler 并发送回我想要的任何响应。

这是我的假 HttpClientHandler 构建器(我正在使用 Moq)。

    public HttpClientHandler MockHttpClientHandler()
    {
        var requestUri = new Uri("Uri.Expected.To.Be.Called");
        var expectedResponse = "Response text"; <-- This is where i need to write the Object to be returned.

        var mockResponse = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(expectedResponse) };
        var mockHandler = new Mock<HttpClientHandler>();
        mockHandler
            .Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                ItExpr.Is<HttpRequestMessage>(message => message.RequestUri == requestUri),
                // ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
            .Returns(Task.FromResult(mockResponse));

        return mockHandler.Object;
    }

我的测试在尝试运行返回行时中断,因为我发回的任何内容都无法反序列化。我只是不知道我的 Stream 应该是什么样子,我也无法通过调试看到它的内容。

我在这里迷路了。也许我的方法是错误的?

感谢您能给我的任何帮助。

【问题讨论】:

  • 你说的中断是什么意思?它是否抛出异常,断言是否失败?如果是这样,你在断言什么?
  • 有点不相关,但是有一个库,里面有一个叫做 RestClient 的东西。它包装了 HttpClient,在提供各种性能优势的同时,它还引入了一个接口 IRestClient,这意味着您可以更轻松地测试事物,因为您可以模拟您自己的客户端。显然需要引入新的依赖项或一些外部代码并更改您的界面,但它可能值得一看。可以在这里找到github.com/NimaAra/Easy.Common/tree/master/Easy.Common
  • 在我看来,您正在测试 .net 类(这将是 Microsoft 的工作) - 您想要测试的代码行为是什么?
  • 一旦我获取该数据,它就会被发送回请求 Http 调用的主方法,然后处理该数据。问题是进行 Http 调用的方法是通用的,并且它被多次使用,所以我必须伪造每种不同类型的调用。
  • @Dave 如何在 RestClient 中设置授权?因为 defaultRequestHeaders 类型如下。 IDictionary> defaultRequestHeaders = new Dictionary>() 被设置。 client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

标签: c# unit-testing testing moq


【解决方案1】:
        var stream = new MemoryStream();

        var httpResponse = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StreamContent(stream)
        };

        var handlerMock = new Mock<HttpMessageHandler>();
        handlerMock
            .Protected()
            .Setup<Task<HttpResponseMessage>>(
                  "SendAsync",
                  ItExpr.IsAny<HttpRequestMessage>(),
                  ItExpr.IsAny<CancellationToken>())
           .ReturnsAsync(httpResponse);

【讨论】:

    猜你喜欢
    • 2022-11-02
    • 2015-07-21
    • 2015-06-26
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多