gpt4 book ai didi

c++ - 如何在 GoogleTest 中使用 QTimers

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:13:47 28 4
gpt4 key购买 nike

我在单元测试期间遇到一些情况,我希望某些 QTimer 的超时触发某些 QObject 中的某些插槽。目前还不清楚如何执行此测试以及此测试的一些常见缺陷。

最佳答案

这个模式是我发现的有效模式。我怀疑它可能在某种程度上依赖于线程模型,因此我为它提供了 YMMV 的小注释。

假设你有一些

class Foo : public QObject{
...
public:
QTimer* _timer;

public slots:
virtual void onTimeout();
...
}

为简单起见,让我们假装这是一些私有(private)实现类,这就是暴露计时器的原因,并且插槽是虚拟的,以便我们可以模拟它。

class MockFoo : public Foo{
public:
MOCK_METHOD0(onTimeout, void());
}

首先,通常在使用 QTimers 和 Qt 中的其他线程模型时,我们必须修改 google test 的“main”函数:

int main(int argc, char **argv) {
QCoreApplication app(argc, argv);

::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();

QTimer exitTimer;
QObject::connect(&exitTimer, &QTimer::timeout, &app, QCoreApplication::quit);
exitTimer.start();
app.exec();
return ret;
}

接下来,在测试套件中:

TEST_F(Foo_Tests, onTimeout){
MockFoo* foo{new MockFoo};
//using Qt 5 convention, but do what you gotta do for signal spy in your setup
QSignalSpy timeoutSpy(foo->_timer, &QTimer::timeout);
QSignalSpy deleteSpy(foo, &QObject::destroyed);

foo->_timer->setInterval(0);
foo->_timer->setSingleShot(true);

EXPECT_CALL(*foo, onTimeout());

foo->_timer->start();

EXPECT_TRUE(timeoutSpy.wait(100));
foo->deleteLater();
deleteSpy.wait(100);
}

关于此的一些注意事项非常重要:

  1. 即使您在测试套件的其他地方已经有一个 MockFoo,您也需要一个在这个测试中创建和销毁的 MockFoo。我怀疑这与 QTimer 和 Qt 的线程模型/事件循环有关。
  2. 假设您在别处进行类似的测试,它可能是不同的类、不同的套件、不同的命名空间,等等。如果您的 EXPECT_CALL 在这里(或其他一些 google test 测试)未饱和,则使用此模式的下一个测试将失败,但它会提示此测试的期望。
    • 例如:Bar_test 失败:MockFoo::onTimeout 预期被调用一次实际未被调用不满足且处于事件状态
  3. 在退出之前等待对象被销毁是很重要的。这允许 Qt 事件循环处理此对象上的未决操作,即触发槽的超时信号。
  4. 即使实际程序使用非 SingleShot 计时器,在此处以这种方式设置它也可以简化它,这样插槽就不会被多次调用,从而扰乱测试。

关于c++ - 如何在 GoogleTest 中使用 QTimers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33829949/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com