如何结合测试计划程序进行异步调用?
简而言之
command.Execute()
是可以观察到的寒冷。你需要订阅它,而不是使用
await
是的。
考虑到你对
TestScheduler
,我认为你想测试一些涉及时间的东西。但是,从
When should I care about scheduling
章节:
在单元测试中无法控制通过“new thread()”或“task.run”创建的线程。
所以,如果你想检查,例如
Task
在100毫秒内完成,必须等到异步方法完成。当然,那是
不
这种测试
测试计划程序
是命中注定的。
稍长的版本
目的
测试计划程序
是通过在某个时间点将事物置于活动状态和验证状态来验证工作流。因为我们只能在
测试计划程序
,您通常不希望等待真正的异步代码完成,因为无法快速转发实际计算或I/O。请记住,这是关于验证工作流的:
vm.A
在20毫秒时有新值,所以
vm.B
在120毫秒时应该有新的VAL,…
那你怎么能测试SUT呢?
1\n可以使用
scheduler.CreateColdObservable
public class ViewModelTests
{
[Fact]
public void Test()
{
string observed = "";
new TestScheduler().With(scheduler =>
{
var observable = scheduler.CreateColdObservable(
scheduler.OnNextAt(100, "Done"));
observable.Subscribe(value => observed = value);
Assert.Equal("", observed);
scheduler.AdvanceByMs(99);
Assert.Equal("", observed);
scheduler.AdvanceByMs(1);
Assert.Equal("Done", observed);
});
}
}
在这里我们基本上取代了
command.execute()
具有
var observable
创建于
scheduler
是的。
很明显上面的例子相当简单,但是有几个观察结果相互通知,这种测试可以提供有价值的见解,以及重构时的安全网。
裁判:
2.您可以引用
IScheduler
明确地
a)使用由
RxApp
public class MyViewModel : ReactiveObject
{
public string Observed { get; set; }
public MyViewModel()
{
Observed = "";
this.MyCommand = ReactiveCommand
.CreateFromTask(SomeAsyncMethod);
}
public ReactiveCommand<Unit, Unit> MyCommand { get; }
private async Task SomeAsyncMethod()
{
await RxApp.TaskpoolScheduler.Sleep(TimeSpan.FromMilliseconds(100));
Observed = "Done";
}
}
public class ViewModelTests
{
[Fact]
public void Test()
{
new TestScheduler().With(scheduler =>
{
var vm = new MyViewModel();
vm.MyCommand.Execute().Subscribe();
Assert.Equal("", vm.Observed);
scheduler.AdvanceByMs(99);
Assert.Equal("", vm.Observed);
scheduler.AdvanceByMs(1);
Assert.Equal("Done", vm.Observed);
});
}
}
注意
b)通过构造函数注入管理自己的调度程序
public class MyViewModel : ReactiveObject
{
private readonly IScheduler _taskpoolScheduler;
public string Observed { get; set; }
public MyViewModel(IScheduler scheduler)
{
_taskpoolScheduler = scheduler;
Observed = "";
this.MyCommand = ReactiveCommand
.CreateFromTask(SomeAsyncMethod);
}
public ReactiveCommand<Unit, Unit> MyCommand { get; }
private async Task SomeAsyncMethod()
{
await _taskpoolScheduler.Sleep(TimeSpan.FromMilliseconds(100));
Observed = "Done";
}
}
public class ViewModelTests
{
[Fact]
public void Test()
{
new TestScheduler().With(scheduler =>
{
var vm = new MyViewModel(scheduler); ;
vm.MyCommand.Execute().Subscribe();
Assert.Equal("", vm.Observed);
scheduler.AdvanceByMs(99);
Assert.Equal("", vm.Observed);
scheduler.AdvanceByMs(0);
Assert.Equal("Done", vm.Observed);
});
}
}
裁判:
让我们用haacked的另一句话来接近:
不幸的是,下一点很重要,
测试计划程序
不会延伸到现实生活中,所以你的恶作剧仅限于异步反应代码。因此,如果你打电话
Thread.Sleep(1000)
在您的测试中,该线程将真正被阻塞一秒钟。但就测试调度程序而言,没有时间过去。