单元测试时间间隔动作与Thread.Sleep不好吗?

Jef*_*f B 7 .net unit-testing sleep timed timed-events

如果我有一个正在测试的主题,计时器会导致某个时间间隔采取某些动作,那么测试它的好方法是什么?

一种方法 是将计时器包装在接口中并将其作为依赖项注入.

但是,我想避免创建另一个抽象.似乎我可以通过注入更新间隔而不是计时器来避免这种情况.然后在我的测试(假设测试的AAA风格),我把Thread.Sleep与前断言,使用非常小的时间值,使测试并不需要很长时间才能运行.

这是个坏主意吗?我知道它可能并不完全遵循TDD的原则,但似乎必须有一条线,你可以通过合同并注入它来阻止所有事情.

Mar*_*age 6

如果您睡眠的数量对测试没有任何意义,您可以将i设置为1毫秒,那么在测试中只需睡眠1毫秒即可.

但是,如果要测试具有超时的复杂计时行为以及在特定时间点采取的特定操作,则很容易抽象出时间概念并将其作为依赖项注入.然后,您的测试可以在虚拟时间内运行,并且即使代码的运行就像实时传递一样,也可以毫不拖延地执行.

虚拟化时间的一种简单方法是使用以下内容:

interface ITimeService {

  DateTime Now { get; }

  void Sleep(TimeSpan delay);

}

class TimeService : ITimeService {

  public DateTime Now { get { return DateTime.UtcNow; } }

  public void Sleep(TimeSpan delay) { Thread.Sleep(delay); }

}

class TimeServiceStub : ITimeService {

  DateTime now;

  public TimeServiceStub() {
    this.now = DateTime.UtcNow;
  }

  public DateTime Now { get { return this.now; } }

  public void Sleep(TimeSpan delay) {
    this.now += delay;
  }

}
Run Code Online (Sandbox Code Playgroud)

如果你需要更多的反应行为,如定时器射击等,你将不得不扩展这个想法.