【发布时间】:2020-08-28 20:33:13
【问题描述】:
我有一个方法应该进行 http 调用,并且应该不再等待响应超时。如果在超时时间内没有收到响应,方法应该返回空字符串,BUT 响应必须在以后处理。
async Task<string> GetResponseOrContinue(int timeout, Action<string> responseHandler)
{
var task = Task.Run(async () =>
{
var response = await _webClient.UploadStringTaskAsync("url", "");
responseHandler(response);
return response;
});
var emptyTask = Task.Run(async () =>
{
await Task.Delay(timeout);
return string.Empty;
});
return await await Task.WhenAny(task, emptyTask);
}
为了简单起见,我省略了 try/catch 和其他细节... 这段代码似乎有效,但我坚持尝试测试它。
我编写的测试几乎总是可以正常工作,但有时这个超时的东西会出现问题并且测试失败。
我使用 Moq 框架模拟 UploadStringTaskAsync 调用:
certWebClient.Setup(x => x.UploadStringTaskAsync(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(() =>
{
Thread.Sleep(timeout + 10);
return "this response will be received after timeout";
});
然后将此 timeout 变量传递给GetResponseOrContinue 方法。看起来很简单,但它并不可靠......
这里有什么问题,也许有更合适的解决方案来解决此类问题?
【问题讨论】:
-
不要在异步代码中使用
Thread.Sleep,await Task.Delay(timeout + 10)是首选方式 -
@PavelAnikhouski 我也用
await Task.Delay(doPaymentTimeout + 1)尝试过,但没有成功... -
stackoverflow.com/questions/49338398/… 有帮助吗?这个想法是在
[Test]中使用async Task方法,以便您可以等待对GetResponseOrContinue的调用。 -
CancellationToken 可能是支持异步调用超时的更好模式。见docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
标签: c# unit-testing .net-core nunit moq