3

当我这样做时:

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"

这仍然不是我想要的行为,但是你去。

4

3 回答 3

6

您可能需要考虑如何使用TestScheduler

它通常在适当的时候执行。例如,此代码将写入控制台:

var scheduler = new TestScheduler();

scheduler.Schedule(
    TimeSpan.FromTicks(100),
    () => Console.WriteLine("Hello"));

scheduler.AdvanceTo(100);

但是,TestScheduler只会在时间移动时检查它的队列。因此,如果您安排一个操作,您需要通过 移动时间AdvanceByAdvanceTo或者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往往用于更苛刻的测试场景,您需要测试一些中间状态 - 即使这样,您通常也会先将所有内容排入适当的到期时间,然后AdvanceByAdvanceTo您感兴趣的时间,检查状态,然后再次使用AdvanceBy,AdvanceToStart

您通常不想做的是排队工作,运行一点,排队更多工作,运行一点 - 特别是如果您在没有到期时间的情况下进行调度。然后你会遇到这里的问题。

这并不是说在您的特定场景中这可能是不可避免的 - 例如,如果您需要决定在特定时间之后安排什么 - 但请考虑您是否可以提前设置所有内容,因为它可能会导致更清晰的测试代码更接近于 Arrange Act Assert 模式。

我尝试通过调度来安排,然后通过移动时间来行动,然后断言结果。

于 2013-06-03T22:27:37.887 回答
1

用于AdvanceBy(1)将调度程序推进 1 个刻度。调度程序仅在时钟实际提前时执行事件。

当您安排立即执行的某事时,不同的调度程序会表现出不同的行为。他们中的一些人确实会立即执行它。有些人将它排在队列中,以便在第一个可用的机会时执行。

在这种情况下,除非修改 API 以让您告诉它它应该以哪种方式运行,否则在这种情况下没有一种好的TestScheduler行为方式。

于 2013-06-03T14:45:10.003 回答
0

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);
于 2022-01-17T19:12:30.503 回答