我正在测试一个类,该类的属性值经常变化,具体取决于它从另一个组件接收的通信。如果该类在5秒内未收到任何通信,则该属性将恢复为默认值。
我很容易存根和模拟通信组件,以便触发我想要测试的值。问题是如果我在繁忙的机器上运行我的单元测试(比如构建机器),并且有足够的延迟导致属性默认,那么我的单元测试将失败。
在模拟各种通信条件时,您将如何测试以确保此属性具有正确的值?
一个想法是重构我的代码,以便我可以存根控制超时的类的部分。另一种方法是编写我的单元测试,以便它可以检测是否由于超时而失败,并在测试结果中指出。
答案 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);
}
也许你可以使用同样的技巧来暂停?