Ger*_*els 2 unit-testing system.reactive
我一直在读这个:使用虚拟时间调度测试Rx查询
我到了"使用单元测试项目"部分(大约在页面的一半)并自己尝试(使用VS2012和MSTest),但我的结果与文档中的结果不同.具体来说,我的断言失败了.
这是我的测试代码:
[TestMethod]
public void TestMethod1()
{
var scheduler = new TestScheduler();
var xs = scheduler.CreateColdObservable(
OnNext(10, 42),
OnCompleted<int>(20));
var observer1 = scheduler.CreateObserver<int>();
scheduler.Schedule(TimeSpan.FromTicks(190),
(s, t) => xs.Subscribe(observer1));
var observer2 = scheduler.CreateObserver<int>();
scheduler.Schedule(TimeSpan.FromTicks(220),
(s, t) => xs.Subscribe(observer2));
scheduler.Start();
observer1.Messages.AssertEqual(
OnNext(200, 42),
OnCompleted<int>(210));
observer2.Messages.AssertEqual(
OnNext(230, 42),
OnCompleted<int>(240));
}
Run Code Online (Sandbox Code Playgroud)
我必须做的一个改变是:
scheduler.Schedule(TimeSpan.FromTicks(190),
() => xs.Subscribe(observer1));
Run Code Online (Sandbox Code Playgroud)
成为:
scheduler.Schedule(TimeSpan.FromTicks(190),
(s, t) => xs.Subscribe(observer1));
Run Code Online (Sandbox Code Playgroud)
说实话,我没有意识到这种变化的影响(我没有在C#中编写那么久!).
以下是结果:
Assert.Fail failed.
Expected: [OnNext(42)@200, OnCompleted()@210]
Actual..: [OnNext(42)@11, OnCompleted()@21]
Run Code Online (Sandbox Code Playgroud)
我理解它的方式是我创建一个冷可观察量,它将在第10个刻度上返回值42,并且序列在第20个刻度处完成.然后,我创建和观察者订阅这个观察者,表示我希望计划从标记190开始.因此,在标记200(190 + 10)处测试值42,在标记210处测试完成时间.然而,我得到标记11和分别为21.
该文档基于V2的RTM之前,因此我不确定TestMcheduler的行为是否已在RTM中更改,或者我是否在某处犯了错误.如果有人能解释发生了什么,我会很感激.
小智 8
您似乎忘记了导入System.Reactive.Concurrency命名空间,其中定义了您要使用的计划重载.这解释了为什么你必须改变代码 - 便利扩展方法可能没有出现:
using System.Reactive.Concurrency;
Run Code Online (Sandbox Code Playgroud)
您正在使用的Schedule的重载是用于立即调度的重载,将TimeSpan值作为TState参数传递:
public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
Run Code Online (Sandbox Code Playgroud)
因此,当调度程序在时间0开始时,将立即执行对xs的预订.每个工作项增加时钟(在测试调度程序上不会同时发生任何事件,模拟单个执行线程),因此您将看到在时间1的一个序列订阅和在时间2的另一个序列订阅
一种可能的解决方法是使用以下内容:
var observer1 = scheduler.CreateObserver<int>();
scheduler.ScheduleAbsolute(190, () => xs.Subscribe(observer1));
var observer2 = scheduler.CreateObserver<int>();
scheduler.ScheduleAbsolute(220, () => xs.Subscribe(observer2));
Run Code Online (Sandbox Code Playgroud)
确保导入System.Reactive.Concurrency命名空间以查找这些重载.您也可以使用ScheduleRelative,因为调度程序尚未启动,到期时间将是当前调度程序的Clock值(= 0)加上指定的相对持续时间.
或者,您也可以使用DateTimeOffset或TimeSpan重载来浏览IScheduler API表面.小心选择正确的过载(使用F12 - 转到定义 - 查看您选择的过载).
var observer1 = scheduler.CreateObserver<int>();
scheduler.Schedule(TimeSpan.FromTicks(190), () => xs.Subscribe(observer1));
var observer2 = scheduler.CreateObserver<int>();
scheduler.Schedule(TimeSpan.FromTicks(220), () => xs.Subscribe(observer2));
Run Code Online (Sandbox Code Playgroud)
同样,请确保使用using指令导入System.Reactive.Concurrency命名空间以查看此重载:-).