如何模拟httpclient

时间:2019-05-15 09:42:37

标签: c# .net-core nunit moq

我是TDD的新手,请您使用moq编写以下测试代码的测试用例-

public async Task<Model> GetAssetDeliveryRecordForId(string id)
    {
        var response = await client.GetAsync($"api/getdata?id={id}");

        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadAsAsync<Model>();

        return result;
    }

谢谢。

1 个答案:

答案 0 :(得分:2)

您可以使用Moq对其进行模拟。

  

使用Moq为您完成

     

现在,您可能不想为每个响应创建一个新的类。   您可以编写一个辅助类来测试您可以使用的测试   您可能需要任何响应,但这可能并不灵活   足够。

     

Moq是一个流行的.NET库,可帮助模拟对象以进行测试。   本质上,它使用反射和表达式来动态生成   根据您的规范,在测试期间在运行时模拟   使用流畅的API进行声明。

     

现在,这里也有一个小问题。如您所见,SendAsync   抽象HttpMessageHandler类上的方法受到保护。的   注意:Moq不能像实现自动生成保护那样简单   接口或公共方法。原因是,流利的API   在模拟的类型上使用表达式,但这不能提供私有或   受保护的成员,因为您从此处从外部访问课程。所以,   我们必须使用Moq的一些更高级的功能来模拟我们的   受保护的方法。

     因此,

Moq具有用于此的API。您确实要使用最小起订量。受保护;在你的   using子句,然后您可以使用   .Protected()方法。这为您提供了一些其他方法   最小起订量,您可以在其中使用受保护成员的名称。

     

使用Moq使用HttpClient对类进行完整的测试看起来   像这样:

// ARRANGE
var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
handlerMock
   .Protected()
   // Setup the PROTECTED method to mock
   .Setup<Task<HttpResponseMessage>>(
      "SendAsync",
      ItExpr.IsAny<HttpRequestMessage>(),
      ItExpr.IsAny<CancellationToken>()
   )
   // prepare the expected response of the mocked http call
   .ReturnsAsync(new HttpResponseMessage()
   {
      StatusCode = HttpStatusCode.OK,
      Content = new StringContent("[{'id':1,'value':'1'}]"),
   })
   .Verifiable();

// use real http client with mocked handler here
var httpClient = new HttpClient(handlerMock.Object)
{
   BaseAddress = new Uri("http://test.com/"),
};

var subjectUnderTest = new MyTestClass(httpClient);

// ACT
var result = await subjectUnderTest
   .GetSomethingRemoteAsync('api/test/whatever');

// ASSERT
result.Should().NotBeNull(); // this is fluent assertions here...
result.Id.Should().Be(1);

// also check the 'http' call was like we expected it
var expectedUri = new Uri("http://test.com/api/test/whatever");

handlerMock.Protected().Verify(
   "SendAsync",
   Times.Exactly(1), // we expected a single external request
   ItExpr.Is<HttpRequestMessage>(req =>
      req.Method == HttpMethod.Get  // we expected a GET request
      && req.RequestUri == expectedUri // to this uri
   ),
   ItExpr.IsAny<CancellationToken>()
);
  

对于单元测试,您不模拟HttpClient。相反,你嘲笑   HttpMessageHandler,将其放入HttpClient并返回   随便你怎么想如果您不想创建特定的   每次测试都派生HttpMessageHandler,也可以有Moq   自动为您创建模拟。

阅读整篇文章here