所以让我首先说我已经看到了创建包装器与嘲笑HttpMethodRequest之间的战争的所有线程。过去,我已经成功地完成了包装器方法,但我认为我会走上模拟 HttpMessageRequest 的道路。
对于初学者来说,这里有一个辩论的例子:在单元测试中模拟HttpClient。我想补充一点,这不是关于这个的。
我发现我有一个注入HttpClient的测试。我一直在做很多无服务器 aws lambda,基本流程是这样的:
//some pseudo code
public class Functions
{
public Functions(HttpClient client)
{
_httpClient = client;
}
public async Task<APIGatewayResponse> GetData(ApiGatewayRequest request, ILambdaContext context)
{
var result = await _client.Get("http://example.com");
return new APIGatewayResponse
{
StatusCode = result.StatusCode,
Body = await result.Content.ReadStringAsAsync()
};
}
}
...
[Fact]
public void ShouldDoCall()
{
var requestUri = new Uri("http://example.com");
var mockResponse = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(expectedResponse) };
var mockHandler = new Mock<HttpClientHandler>();
mockHandler
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
It.IsAny<HttpRequestMessage>(),
It.IsAny<CancellationToken>())
.ReturnsAsync(mockResponse);
var f = new Functions(new HttpClient(handler.Object);
var result = f.GetData().Result;
handlerMock.Protected().Verify(
"SendAsync",
Times.Exactly(1), // we expected a single external request
ItExpr.Is<HttpRequestMessage>(req =>
req.Method == HttpMethod.Get &&
req.RequestUri == expectedUri // to this uri
),
ItExpr.IsAny<CancellationToken>()
);
Assert.Equal(200, result.StatusCode);
}
所以这就是我遇到问题的地方!
当我所有的测试都在NCrunch
运行时,它们通过了,而且通过得很快!
当我使用Resharper 2018
手动运行它们时,它们会失败。
同样,当它们在CI/CD平台(Linux发行版上具有网络核心2.1 SDK的docker容器(中运行时,它们也会失败。
这些测试不应并行运行(以这种方式读取测试默认值(。我围绕这些方法组合了大约 30 个测试,每个测试在 moq 验证部分随机失败。有时他们通过,有时他们失败。如果我分解每个测试类的测试并以这种方式运行组,而不是全部在一个组中,那么这些都将以块的形式传递。我还要补充一点,我什至尝试隔离每个测试方法的变量以确保没有重叠。
所以,我真的迷失了试图通过这里处理这个问题并确保这是可测试的。
有没有不同的方法可以接近HttpClient
,它可以持续通过?
经过很多次来回。我从中发现了两种情况。
-
我无法在 docker 设置中禁用并行处理,这就是我认为问题所在(我什至让它在测试之间进行线程睡眠以减慢速度(这对我来说真的很恶心(
-
我发现所有通过测试运行器本地运行的测试都告诉我,当大约 1/2 在 docker 测试运行器上失败时,它们通过了。最终成为问题的是在查看和获取环境变量时出现一个魔术字符串区域。
需要 注意的是,亚马逊更新了他们的.NET Core lambda工具,通过
dotnet
cli进行安装,因此在我们的docker镜像中进行了更新。