测试运行器与 HttpClient 和 Mocking HttpMessageRequest XUnit 不一致
Test runners inconsistent with HttpClient and Mocking HttpMessageRequest XUnit
所以让我首先说我已经看到了创建包装器与模拟 HttpMethodRequest 之间的所有争论。过去,我使用包装器方法取得了巨大的成功,但我想我应该走模拟 HttpMessageRequest 的道路。
首先,这里是 辩论 的一个例子:。我想补充一点,这不是本文的重点。
我发现我对注入 HttpClient 的测试进行了测试。我一直在做很多无服务器 aws lambdas,基本流程是这样的:
//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 平台中获得 运行 时,这是一个 docker 容器,在 Linux 发行版上带有 net core 2.1 SDK,他们也失败。
这些测试不应 运行 并行(以这种方式读取测试默认值)。我围绕这些方法进行了大约 30 次测试,每一次都在最小起订量验证部分随机失败。 有时他们通过,有时他们失败。 如果我按测试 class 和 运行 那样分解测试组,而不是全部放在一个组中,那么这些都将成块传递。我还要补充一点,我什至尝试隔离每个测试方法的变量以确保没有重叠。
所以,我真的迷失了尝试通过这里处理这个问题并确保它是可测试的。
是否有不同的方法来接近 HttpClient
它可以持续通过的地方?
经过很多来回。我从中发现了两种情况。
我无法在 docker 设置中禁用并行处理,这是我认为的问题所在(我什至让它在测试之间进行线程休眠以减慢速度(我觉得很恶心)
我发现通过测试运行器在本地 运行 进行的所有测试都告诉我它们通过了,而 docker 测试运行器上大约有 1/2 失败了。最终成为问题的是查看和获取环境变量时的 魔术字符串 区域。
需要注意的一点是,Amazon 更新了他们的 .NET Core lambda 工具以通过 dotnet
cli 安装,因此在我们的 docker 图像中进行了更新。
所以让我首先说我已经看到了创建包装器与模拟 HttpMethodRequest 之间的所有争论。过去,我使用包装器方法取得了巨大的成功,但我想我应该走模拟 HttpMessageRequest 的道路。
首先,这里是 辩论 的一个例子:
我发现我对注入 HttpClient 的测试进行了测试。我一直在做很多无服务器 aws lambdas,基本流程是这样的:
//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 平台中获得 运行 时,这是一个 docker 容器,在 Linux 发行版上带有 net core 2.1 SDK,他们也失败。
这些测试不应 运行 并行(以这种方式读取测试默认值)。我围绕这些方法进行了大约 30 次测试,每一次都在最小起订量验证部分随机失败。 有时他们通过,有时他们失败。 如果我按测试 class 和 运行 那样分解测试组,而不是全部放在一个组中,那么这些都将成块传递。我还要补充一点,我什至尝试隔离每个测试方法的变量以确保没有重叠。
所以,我真的迷失了尝试通过这里处理这个问题并确保它是可测试的。
是否有不同的方法来接近 HttpClient
它可以持续通过的地方?
经过很多来回。我从中发现了两种情况。
我无法在 docker 设置中禁用并行处理,这是我认为的问题所在(我什至让它在测试之间进行线程休眠以减慢速度(我觉得很恶心)
我发现通过测试运行器在本地 运行 进行的所有测试都告诉我它们通过了,而 docker 测试运行器上大约有 1/2 失败了。最终成为问题的是查看和获取环境变量时的 魔术字符串 区域。
需要注意的一点是,Amazon 更新了他们的 .NET Core lambda 工具以通过
dotnet
cli 安装,因此在我们的 docker 图像中进行了更新。