轻松编写保持状态的模拟
Easily writing mocks that hold state
我正在测试一些大量使用回调的代码,它看起来像这样:
class Client {
public:
Client(Socket socket) {
socket->onA([this] {
// call private Client methods....
});
socket->onB([this] {
// call private Client methods...
});
// repeated for onC, onD, and onE
}
void Start();
void Stop();
private:
// and almost all of the state is private
};
它几乎完全通过Socket
提供的接口与外界通信,看起来像:
class Socket {
public:
void onA(std::function<void()> callBack) = 0;
void onB(std::function<void()> callBack) = 0;
void onC(std::function<void()> callBack) = 0;
void onD(std::function<void()> callBack) = 0;
void onE(std::function<void()> callBack) = 0;
// various other public methods
};
重要的是,我既可以验证onX
函数是否已被调用,也可以访问传递给它们的参数(因为Client
的状态会随着来自Socket
的通知而变化,所以我需要在测试中模拟它们)。
我可以写一个模拟,看起来像:
class MockSocket : public Socket {
public:
MOCK_METHOD1(onA, void(std::function<void()> callBack));
MOCK_METHOD1(onB, void(std::function<void()> callBack));
// etc
};
但我需要能够写下形式的期望值:"期望这个MockSocket
对象的onA
方法被调用一次,现在调用作为参数传递给onA
的函数。现在检查Socket
的write
方法是否用这个字符串调用:……"
在另一个例子中,当我只有一个这样的功能时,我做了一些类似的事情:
class MockSocket : public Socket {
public:
// as before
void setCallbackForA(std::function<void()> callBack) {
callbackForA = callBack;
}
void callCallbackForA() {
callbackForA();
}
// etc
private:
std::function<void()> callbackForA;
std::function<void()> callbackForB;
// etc
};
但要完成这项工作,将需要大量的样板(5个getter和5个setter+所有的EXPECT_CALL
,从一个测试用例到另一个测试案例,这将非常轻微),我怀疑必须有更好的方法来做到这一点(不使用C风格的宏)。有什么模板魔法可以帮助吗?有什么可以让它更容易处理的吗?
我假设您正在测试Client
类,所以您真正需要的是存储Client
在Socket
中注册的回调函数。通过SaveArg<N>
操作执行此操作。参见代码:
class ClientTest : public ::testing::Test
{
public:
std::function<void()> onACallback;
std::function<void()> onBCallback;
//...
MockSocket mockSocket;
std::unique_ptr<Client> objectUnderTest;
void SetUp() override
{
using ::testing::SaveArg;
EXPECT_CALL(mockSocket, onA(_)).WillOnce(SaveArg<0>(&onACallback));
EXPECT_CALL(mockSocket, onB(_)).WillOnce(SaveArg<0>(&onBCallback));
//...
objectUnderTest = std::make_unique<Client>(mockSocket);
}
};
使用上面的Test类,您可以收集所有回调。您可以使用这些捕获的回调来触发Client类中的操作,就像下面的测试用例一样:
TEST_F(ClientTest, shallDoThisAndThatOnA)
{
// here you put some expectations
//...
onACallback(); // here you trigger your Client object under test
// now you make some assertions (post actions)
//...
}
相关文章:
- 如何使用Google Mock来模拟gettimeofday()
- G锁定铸造到基础上会释放模拟行为
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 落砂模拟碰撞检测C++和SFML
- 我不断收到 [错误] ID 返回 1 退出状态错误,但看不到问题所在
- OSX MetalKit CVMetalTextureCacheCreateTextureFromImage失败,状态:
- 在gtest.中使用fff.h模拟系统API
- 谷歌模拟和覆盖关键字
- 用C#中的并集模拟C++嵌套结构
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- std::future_error:无关联状态
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 如何避免LED在循环状态变化中闪烁?
- boost 是否有按特殊类型值编码状态"compact optional"?
- 如何模拟不同边数的骰子滚动?
- 为什么系统函数总是在C++中返回已转移的退出状态?
- 如何将用户返回到模拟前的状态
- 轻松编写保持状态的模拟