Mis*_*hex 7 tdd unit-testing task-parallel-library system.reactive async-await
如何单元测试具有等待Task.Delay的组件,而不必等待它.
例如,
public void Retry()
{
// doSomething();
if(fail)
await Task.Delay(5000);
}
Run Code Online (Sandbox Code Playgroud)
我需要测试失败分支,但我不希望我的测试等待5秒.
在任务并行库中是否有类似rx虚拟时间调度的功能?
计时器只是外部依赖的另一种形式.唯一的区别是它取决于时钟而不是数据库.和任何其他外部依赖一样,它使测试变得困难; 因此,答案是改进设计,直到它易于测试.
遵循依赖注入原则建议您应该在对象的构造函数中传递计时器,这使您能够注入测试存根而不是依赖于实时计时器.
请注意这可以改善您的设计.在许多情况下,超时时间根据谁的呼叫而变化.这将建立超时期限的责任转移到等待它的应用程序层.这层应该了解它愿意等多久.
任务并行库中是否有类似 rx 虚拟基于时间的调度之类的东西?
不,那里没有。您的选择是定义可以使用测试存根实现的“计时器服务”,或者使用 Microsoft Fakes 拦截对Task.Delay. 我更喜欢后者,但它只是 VS Ultimate 上的一个选项。
1) 定义您自己的 Task.Delay 实现。
public static class TaskEx
{
private static bool _shouldSkipDelays;
public static Task Delay(TimeSpan delay)
{
return _shouldSkipDelays ? Task.FromResult(0) : Task.Delay(delay);
}
public static IDisposable SkipDelays()
{
return new SkipDelaysHandle();
}
private class SkipDelaysHandle : IDisposable
{
private readonly bool _previousState;
public SkipDelaysHandle()
{
_previousState = _shouldSkipDelays;
_shouldSkipDelays = true;
}
public void Dispose()
{
_shouldSkipDelays = _previousState;
}
}
}
Run Code Online (Sandbox Code Playgroud)
2) 在代码中的任何地方都使用 TaskEx.Delay 而不是 Task.Delay。
3) 在您的测试中使用 TaskEx.SkipDelays:
[Test]
public async Task MyTest()
{
using (TaskEx.SkipDelays())
{
// your code that will ignore delays
}
}
Run Code Online (Sandbox Code Playgroud)