带有超时的单元测试

发布于 2024-09-04 05:48:39 字数 316 浏览 3 评论 0原文

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

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

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

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

I am unit testing a class with a property whose value changes often, depending on communication it receives from another component. If the class does not receive any communication for 5 seconds, the property reverts to a default value.

It is easy for me to stub and mock out the communicating component in order to trigger the values I want to test for. The problem is that if I run my unit tests on a machine which is busy (like a build machine), and there is a significant-enough delay to cause the property to default, then my unit test will fail.

How would you test to be sure that this property has the proper value when simulating various communication conditions?

One idea is to restructure my code so that I can stub the part of the class which controls the timeout. Another is to write my unit test such that it can detect if it failed due to a timeout and indicates that in the test results.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

豆芽 2024-09-11 05:48:39

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

I'd try a different approach. Game developers often need a way to control the game time, e.g. for fast-forward functionality or to synchronize frame rates. They introduce a Timer object, which reads ticks from either a hardware clock, or from a simulated clock.

In your case, you could provide a controllable timer for your unit tests and a timer which delegates to system time in production mode. That way, you can control the time which passes for your test case and thus how the class-under-test has to react under certain timeout conditions.

Pseudo-code:

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();
}
╰ゝ天使的微笑 2024-09-11 05:48:39

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

You could make the timeout property configurable, then set it to a high enough value in your unit tests (or low enough, if you want to unit test the reset behaviour).

稍尽春風 2024-09-11 05:48:39

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

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

There is a similar problem when using DateTime.Now.
Ayende described a trick to deal with it that I liked:

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

and then in your test :

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

Maybe you can use the same kind of trick for your timeout?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文