当我这样做时:
testScheduler.Schedule("Hello world",(scheduler, state) => Console.WriteLine(state));
testScheduler.AdvanceTo(testScheduler.Now);
我在VirtualTimeSchedulerBase
:
public void AdvanceTo(TAbsolute time)
{
int num = this.Comparer.Compare(time, this.Clock);
if (num < 0)
throw new ArgumentOutOfRangeException("time");
if (num == 0)
return;
num == 0
为真,退出该方法。
我可以调用testScheduler.Start()
,我的动作将执行。但是TestScheduler
将继续执行其队列中的所有内容。而我希望它在当前时间停止执行操作。
我在TestScheduler上看不到任何其他方法可以让我得到我想要的行为。
这是一个错误,还是正确的行为,但我错过了什么?
编辑:我误解了。TestScheduler
不执行操作,直到在之后的日期,他们被安排。
调度操作立即调度它的当前值testScheduler.Now
。所以直到Now + 1
.
var testScheduler = new TestScheduler();
var due = new DateTime();
testScheduler.Schedule("Hello world", due, (scheduler, s) =>
{
Console.WriteLine(s);
return Disposable.Empty;
});
testScheduler.AdvanceTo(due.Ticks);
// Nothing has happened
testScheduler.AdvanceTo(due.Ticks+1);
// -> "Hello world"
这仍然不是我想要的行为,但这就是。
您可能需要考虑如何使用TestScheduler
:
It 通常会在适当的时间执行。例如,以下代码将写入控制台:
var scheduler = new TestScheduler();
scheduler.Schedule(
TimeSpan.FromTicks(100),
() => Console.WriteLine("Hello"));
scheduler.AdvanceTo(100);
然而,TestScheduler
只会在移动时间时检查它的队列。因此,如果您安排一个操作,您需要通过AdvanceBy
、AdvanceTo
或Start
移动时间,以使其处理队列。当它运行时,它将处理截至当前时间的所有内容。例:尽管调度"过去",即使这样也会输出到控制台:
var scheduler = new TestScheduler();
scheduler.AdvanceTo(TimeSpan.FromTicks(100).Ticks);
scheduler.Schedule(
DateTime.MinValue + TimeSpan.FromTicks(50),
() => Console.WriteLine("Hello"));
Console.WriteLine("No output until the scheduler is given time...");
scheduler.AdvanceBy(1);
TestScheduler
的习惯用法通常包括将所有工作排队,然后通过Start()调用运行到完成,然后检查预期状态。使用AdvanceBy
, AdvanceTo
往往是为了更苛刻的测试场景,你需要测试一些中间状态-即使这样,你通常排队所有首先在适当的时间,然后AdvanceBy
或AdvanceTo
你感兴趣的时间,检查状态,然后再次使用AdvanceBy
, AdvanceTo
或Start
。
你不想做的通常是队列工作,运行一点,队列更多的工作,运行一点-特别是如果你的调度没有到期时间。然后你就会遇到这里的问题。
这并不是说在您的特定场景中这可能是不可避免的-例如,如果您需要决定在特定时间之后安排什么-但是考虑您是否可以提前设置所有内容,因为它可能会导致更干净的测试代码,更紧密地遵循Arrange Act Assert模式。
我尝试通过调度来安排,然后通过移动时间来行动,然后断言结果
使用AdvanceBy(1)
将调度器提前1个刻度。调度程序只在时钟实际前进时执行事件。
不同的调度程序在为立即执行调度时表现不同。他们中的一些人真的会立即执行。有些人把它放在一个队列中,在第一个可用的机会执行。
在这种情况下,TestScheduler
没有一个好的行为方式,除非API被修改,让你告诉它应该以哪种方式行事。
Start
方法将执行计划的所有内容。您可以调度Stop
方法调用,在给定的点暂停执行。
var testScheduler = new TestScheduler();
var due = new DateTime();
testScheduler.Schedule("Hello world", due, (scheduler, s) =>
{
Console.WriteLine(s);
return Disposable.Empty;
});
testScheduler.Schedule(due.Ticks + 1, (scheduler, s) => testScheduler.Stop());
testScheduler.Schedule("Do more stuff", due.AddMinutes(1), (scheduler, s) => Console.WriteLine(s));
testScheduler.Start();
Assert.IsFalse(testScheduler.IsEnabled);
Assert.AreEqual(due.Ticks + 1, testScheduler.Clock);