使用超时进行单元测试

9
我正在对一个类进行单元测试,该类具有一个属性,其值经常会因另一个组件的通信而改变。如果该类在5秒内没有收到任何通信,则该属性将恢复为默认值。
我可以轻松地存根和模拟通信组件以触发我想要测试的值。问题是,如果我在一个繁忙的机器上运行我的单元测试(比如构建机器),并且存在足够长的延迟导致属性默认,那么我的单元测试将失败。
你如何测试以确保在模拟各种通信条件时该属性具有正确的值?
一个想法是重构我的代码,以便我可以存根控制超时的类部分。另一个方法是编写我的单元测试,使其能够检测是否由于超时而失败,并在测试结果中指示此情况。
3个回答

11

我会尝试一种不同的方法。游戏开发者经常需要控制游戏时间,例如快进功能或同步帧率。他们引入一个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();
}

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

我选择这条路线是因为它对于我的情况来说是最简单的解决方案。其他的建议也很好。谢谢大家! - sourcenouveau

3

使用DateTime.Now时会出现类似的问题。 Ayende提供了一个技巧来解决这个问题,我很喜欢:

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);
}

也许你可以使用同样的技巧来处理超时问题?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接