【问题标题】:C++ Gmock - WillOnce - Can you do anything aside from return a value?C++ Gmock - WillOnce - 除了返回值,你还能做任何事情吗?
【发布时间】:2021-05-28 00:33:23
【问题描述】:

我正在学习 gmock,并且想知道如何在调用其中一个模拟方法时让我的模拟对象执行某些操作。

我需要模拟一些使用 Qt 的接口,我正在尝试让 Qt 和 Gmock 一起工作。

例如,我模拟了一个网络套接字接口类,通过基于构造函数的 DI 将其提供给网络客户端类,并且我想告诉模拟套接字在连接完成时调用其方法之一来向客户端发出信号,按顺序假装建立了联系。

我看到有WillOnce,它需要“行动”,但我正在阅读的文档并没有真正解释“行动”可以是什么类型的东西。所有的例子都只是简单地返回一些东西或增加一个全局变量。你能调用属于你正在模拟的抽象类的方法吗?

如果不是,我看到您可以单独定义一个假对象并使其成为模拟的成员,然后委托,但这似乎需要大量工作才能放入每个想要不同行为的测试用例中.

  • 您必须在界面中定义每一个纯虚拟,无论您是否想为特定的测试用例使用它
  • 似乎我将不得不创建不同的假货,因此当假货行为不同时,每个测试用例的本地模拟都不同 ...例如,也许我想在一个测试用例 a 中打开信号而不在另一个测试用例中发出信号

下面是一些示例代码:

class MySocketInterface : QObject
{
    Q_OBJECT
    public:
   
       virtual void connect(std::string url) = 0;
       
    signal:    // Specific to Qt, but this is what I need to call
       // Notifies subscribers
       void connected();
 }

 class MyThingToTest
 {
 public:
     MyThingToTest(std::unique_ptr<MySocketInterface> && socket);
     void connect(std::string url);
     State getState() const;
 private:
     std::unique_ptr<MySocketInterface> m_socket;
     // Changes state to connected
     void onConnected();
 }

 Test1:
 ) Make a mock socket
 ) Give it to MyThingToTest
 ) Call MyThingToTest::connect
 ) mock socket needs to send notification faking connecting by calling `emit connected`
 ) Check if MyThingToTest is in connected state

 Test2:
 ) Make a mock socket
 ) Give it to MyThingToTest
 ) Call MyThingToTest::connect
 ) mock socket needs to not send notification, and 30 seconds needs to elapse.
 ) Check if MyThingToTest is in an error state

我想避免必须定义一个全新的假类和模拟,将每一个动作不同的单元测试用例委托给它。

请注意,我不是在寻找 QSignalSpy 或验证信号和插槽。我想验证对它们做出反应的类的功能,并让这些类使用模拟依赖项,这样我就不必在真实网络中交谈。

【问题讨论】:

  • 提供了很多默认操作,您可以用它们做很多事情:github.com/google/googletest/blob/master/docs/reference/… 也许它会帮助您更新您的问题,并在概念上尝试编写测试大纲。
  • 我只是这样做:WillOnce(Invoke(&lt;lambda here which returs proper value and does other stuff&gt;))
  • @Marek R 但 lambda 不能在您正在模拟的接口上调用方法,可以吗?
  • lambda 可以调用任何东西,只要您正确捕获变量。
  • @Marek R 我认为它不能调用您正在模拟的接口的私有方法。如果你能做到这一点,很乐意将一些示例代码标记为答案。

标签: c++ qt gmock


【解决方案1】:

假设您使用的是 Qt 5 或更高版本,您应该能够使用 InvokeWithoutArgs 来实现您正在寻找的结果。您的模拟对象应定义如下:

class MockMySocketInterface : public MySocketInterface
{
    Q_OBJECT
public:
    MockMySocketInterface() { }
    virtual ~MockMySocketInterface() { }

    MOCK_METHOD1(connect, void(std::string));
};

您的测试将如下所示:

auto socket = std::make_unique<MockMySocketInterface>(); // Could also use NiceMock here.

// This could alternately be an EXPECT_CALL, but you would need to use WillOnce
// or WillRepeatedly instead of WillByDefault.
ON_CALL(*socket, connect(_))
    .WillByDefault(InvokeWithoutArgs(socket.get(), &MockMySocketInterface::connected));
MyThingToTest thing(socket);

// etc.

【讨论】:

  • 你是最棒的酱料。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 2021-06-02
  • 2014-02-25
  • 2017-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多