Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;Gmock-WillOnce-除了返回值之外,您还能做什么吗?_C++_Qt_Gmock - Fatal编程技术网

C++ C++;Gmock-WillOnce-除了返回值之外,您还能做什么吗?

C++ C++;Gmock-WillOnce-除了返回值之外,您还能做什么吗?,c++,qt,gmock,C++,Qt,Gmock,我正在学习gmock,并且想知道当调用一个模拟方法时,如何使我的模拟对象做一些事情 我需要模拟一些使用Qt的接口,我正在尝试让Qt和Gmock一起工作 例如,我模拟了一个网络套接字接口类,通过基于构造函数的DI将它提供给了一个网络客户端类,我想告诉模拟套接字调用它的一个方法,在连接完成时向客户端发送信号,以便假装建立了连接 我看到有WillOnce,它需要和“行动”,但我正在阅读的文档并没有真正解释“行动”可以是什么样的东西。所有示例都只是返回某个值或增加一个全局变量。您可以调用属于您正在模拟的

我正在学习gmock,并且想知道当调用一个模拟方法时,如何使我的模拟对象做一些事情

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

例如,我模拟了一个网络套接字接口类,通过基于构造函数的DI将它提供给了一个网络客户端类,我想告诉模拟套接字调用它的一个方法,在连接完成时向客户端发送信号,以便假装建立了连接

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

如果没有,我看你可以分别定义一个伪对象,使其成为mock的成员,然后委托,但这似乎需要在每个需要不同行为的测试用例中投入大量的工作

  • 您必须定义接口中的每一个纯虚拟,无论您是否想将其用于特定的测试用例
  • 似乎我必须创建不同的假货,因此,当假货行为不同时,每个测试用例的本地模拟也不同 ... 例如,我可能希望在一个测试用例a中打开信号,而在另一个测试用例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
类MySocketInterface:QObject
{
Q_对象
公众:
虚拟空连接(std::字符串url)=0;
signal://特定于Qt,但这是我需要调用的
//通知订户
空连接();
}
MyThingToTest类
{
公众:
MyThingToTest(std::unique_ptr&socket);
voidconnect(std::stringurl);
State getState()常量;
私人:
std::唯一的ptr m_插座;
//将状态更改为已连接
void onConnected();
}
测试1:
)做一个假插座
)把它交给MyThingToTest
)调用MyThingToTest::connect
)模拟套接字需要通过调用'emit connected'发送假连接通知`
)检查MyThingToTest是否处于连接状态
测试2:
)做一个假插座
)把它交给MyThingToTest
)调用MyThingToTest::connect
)模拟套接字不需要发送通知,需要30秒。
)检查MyThingToTest是否处于错误状态
我想避免必须定义一个全新的伪类,并模拟将每个操作不同的单元测试用例委托给它


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

假设您使用的是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.
auto socket=std::make_unique();//也可以在这里使用NiceMock。
//这也可以是一个EXPECT_调用,但您需要使用WillOnce
//或者重复使用,而不是默认使用。
通话时(*插座,连接())
.WillByDefault(调用wthoutargs(socket.get(),&MockMySocketInterface::connected));
MyThingToTest(插座);
//等等。

提供了很多默认操作,你可以用它们做很多事情:也许用你在概念上试图编写的测试大纲来更新你的问题会有帮助。我只是这样做:
WillOnce(Invoke())
@Marek R但是lambda不能调用你正在模拟的接口上的方法,可以吗?只要你能正确捕获变量,lambda就可以调用任何东西。@Marek R我认为它不能调用你正在模拟的接口的私有方法。如果你能做到这一点,我很乐意标记一些示例代码作为答案。你是最棒的酱汁。