【问题标题】:How can I test a call is made after a delay in google test using a mocking framework如何在使用模拟框架的谷歌测试延迟后测试调用
【发布时间】:2016-01-08 19:01:14
【问题描述】:

我目前正在尝试评估不同的测试框架。在使用模拟框架时(我倾向于 FakeIt,但 google mock 也很好),我知道您可以通过在调用函数之前和之后使用操作系统的计时器调用来滚动自己的“性能”测试来验证函数的性能。这不是我想要的。

我所拥有的是在给定特定输入的情况下实现输出延迟的类。例如:

  • 输入 1 从低到高
  • 输出 1 1.5 秒后从低变高。

我希望能够做一些我指定边界的事情:

myMock.theInput();
EXPECT_CALL(myMock, theDelayedOutput())
  .Times(1)
  .Before(1.6sec)
  .After(1.4sec);

为了澄清,不支持BeforeAfter 行。这只是我喜欢的简单语法的一个示例。

是否可以在进行输入调用和检查EXPECT_CALL之前在窗口中实现“延迟”功能?

这是其中的一部分——我仍然需要启动一个专有计时器。像这样?

myMock.theInput();
windowSleep(1.4);
startTimer();
EXPECT_CALL(myMock, theDelayedOutput())
  .Times(1)
endTimer();
ASSERT_TRUE(elapsedTime() <= 0.2);

【问题讨论】:

    标签: c++ unit-testing googletest gmock fakeit


    【解决方案1】:

    既然你用单元测试标记了这个问题:在单元测试中,你的测试不应该依赖于物理时间的流逝。这有多种原因:一个是您希望测试尽快运行,因此您不希望出现延迟。另一个原因是开发环境(运行单元测试的地方)的时间可能与目标环境完全不同,因为不同的硬件、操作系统、系统负载......

    也就是说,涉及物理时间流逝的测试确实有意义,但它们将是目标系统上的集成测试(或某些模拟)。在单元测试中,您将采用不同的方法:

    您将模拟代表您的时钟的函数/方法。例如,如果您的函数 funcA 通过 setTimer 设置了一个计时器,则提供一个在时间已过时调用的回调:

    • 在您的某些测试中,您模拟 setTimer 函数,调用 funcA,并作为测试通过标准的一部分,检查模拟的 setTimer 是否使用您期望的参数调用。
    • 在其他一些测试中,您可以直接从测试中调用回调函数,以查看该函数的行为是否正确。

    在这两种单元测试用例中,您无需等待物理时间过去。

    也就是说,您当然可以将用于单元测试的相同测试框架也用于集成测试(即使它们的名称,如 JUnit,似乎表明它们仅用于单元测试)。而且,如果集成测试确实是您的目标,那么 Jeff Lamb 的建议肯定会有所帮助。

    【讨论】:

      【解决方案2】:

      我很确定此解决方案适用于任何框架,而无需修改框架:

      myMock.theInput();
      startTimer();
      EXPECT_CALL(myMock, theDelayedOutput());
      endTimer();
      ASSERT_TRUE(elapsedTime() >= 1.4);
      ASSERT_TRUE(elapsedTime() <= 1.6);
      

      然后可以将其包装在宏中:

      #define EXPECT_CALL_DELAYED(theMock, expectCall, lowerBound, upperBound) {\
        startTimer();\
        EXPECT_CALL(theMock, expectCall);\
        endTimer();\
        ASSERT_TRUE(elapsedTime() >= lowerBound);\
        ASSERT_TRUE(elapsedTime() <= upperBound);\
      }
      

      那么最后的测试代码是:

      myMock.theInput();
      EXPECT_CALL_DELAYED(myMock, theDelayedOutput(), 1.4, 1.6);
      

      或者,您可以坚持 DRY 原则并预先指定时间的“窗口”。这允许您进行测试,指定确切的时间,但没有重复自己每次都需要上下添加 0.1 秒缓冲区的缺点。

      EXPECT_CALL_DELAYED_SET_WINDOW(0.1);
      myMock.theInput();
      EXPECT_CALL_DELAYED(myMock, theDelayedOutput(), 1.5);
      myMock.theSecondInput();
      EXPECT_CALL_DELAYED(myMock, theSecondDelayedOutput(), 3.1);
      

      不过,我还没有测试过这些。我稍后会更新,如果可行,我会接受。

      【讨论】:

        猜你喜欢
        • 2011-06-14
        • 2023-03-05
        • 1970-01-01
        • 2022-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多