超时单元测试

时间:2010-06-04 15:59:14

标签: unit-testing timeout

我正在测试一个类,该类的属性值经常变化,具体取决于它从另一个组件接收的通信。如果该类在5秒内未收到任何通信,则该属性将恢复为默认值。

我很容易存根和模拟通信组件​​,以便触发我想要测试的值。问题是如果我在繁忙的机器上运行我的单元测试(比如构建机器),并且有足够的延迟导致属性默认,那么我的单元测试将失败。

在模拟各种通信条件时,您将如何测试以确保此属性具有正确的值?

一个想法是重构我的代码,以便我可以存根控制超时的类的部分。另一种方法是编写我的单元测试,以便它可以检测是否由于超时而失败,并在测试结果中指出。

3 个答案:

答案 0 :(得分:10)

我会尝试不同的方法。游戏开发者通常需要一种控制游戏时间的方法,例如用于快进功能或同步帧速率。它们引入了一个Timer对象,它可以从硬件时钟或模拟时钟读取滴答声。

在您的情况下,您可以为单元测试提供可控定时器,并在生产模式下委托系统时间。这样,您可以控制测试用例的通过时间,从而控制被测试类在某些超时条件下的反应。

的伪代码:

public void testTimeout() throws Exception {
  MockTimerClock clock = new MockTimerClock();

  ClassUnderTest cut = new ClassUnderTest();
  cut.setTimerClock(clock);
  cut.beginWaitingForCommunication();

  assertTrue(cut.hasDefaultValues());
  cut.receiveOtherValues();
  assertFalse(cut.hasDefaultValues());

  clock.tick(5,TimeUnit.SECONDS);
  assertTrue(cut.hasDefaultValues());
  cut.shutdown();
}

答案 1 :(得分:3)

您可以使超时属性可配置,然后在单元测试中将其设置为足够高的值(或者如果您想要对重置行为进行单元测试,则足够低)。

答案 2 :(得分:3)

使用DateTime.Now时存在类似问题。 Ayende described a trick处理我喜欢的事情:

public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

然后在你的测试中:

[Test]
public void Should_calculate_length_of_stay_from_today_when_still_occupied()
{
    var startDate = new DateTime(2008, 10, 1);
    SystemTime.Now = () => new DateTime(2008, 10, 5);

    var occupation = new Occupation { StartDate = startDate };

    occupation.LengthOfStay().ShouldEqual(4);
}

也许你可以使用同样的技巧来暂停?