如何使用 Gmock 连续调用第 n 次 return 一个特定值
How to return a specific value every nth time of a consecutive call with Gmock
在代码 Google 模拟测试片段中有一个 EXPECT_CALL
return 是 True 和一个参数引用 200 次。
怎么才能让测试每n次都return为真呢。例如,每 10 次调用 return True,否则 return False。
class MockHandler : public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
}
TEST(TestDispatcher, HandlePing)
{
auto mockedHandler = make_unique<MockHandler>();
Msg rxMsg = { REQUEST::REQ_PING, sizeof(DefaultMsg_t), rxMsg.rx,(uint8_t*)"0"};
EXPECT_CALL(*mockedHandler,
RxMsg(_)).Times(checkValue).WillRepeatedly(
DoAll(SetArgReferee<0>(rxMsg), Return(TRUE)));
Dispatcher dispatcher(10, mockedHandler);
for (int i = 0; i < 199; i++)
{
dispatcher.RunToCompletion();
}
}
可能适合您的方法很少。我喜欢将 Invoke
作为默认操作的解决方案,因为它是最灵活的。您没有在问题中提供 mcve,所以我为您使用的 类 编写了非常简单的实现。此外,您使用 unique_ptr
作为模拟也犯了一个错误。在 99% 的情况下必须 shared_ptr
,因为您在测试环境和被测系统之间共享它。
class Msg {};
class Handler {
public:
virtual bool RxMsg(Msg &msg) = 0;
};
class MockHandler: public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
};
class Dispatcher {
public:
Dispatcher(std::shared_ptr<Handler> handler): h_(handler) {}
void run() {
Msg m;
std::cout << h_->RxMsg(m) << std::endl;
}
private:
std::shared_ptr<Handler> h_;
};
class MyFixture: public ::testing::Test {
protected:
MyFixture(): mockCallCounter_(0) {
mockHandler_.reset(new MockHandler);
sut_.reset(new Dispatcher(mockHandler_));
}
void configureMock(int period) {
ON_CALL(*mockHandler_, RxMsg(_)).WillByDefault(Invoke(
[this, period](Msg &msg) {
// you can also set the output arg here
// msg = something;
if ((mockCallCounter_++ % period) == 0) {
return true;
}
return false;
}));
}
int mockCallCounter_;
std::shared_ptr<MockHandler> mockHandler_;
std::unique_ptr<Dispatcher> sut_;
};
TEST_F(MyFixture, HandlePing) {
configureMock(10);
for (int i = 0; i < 199; i++) {
sut_->run();
}
}
在每次测试开始时,您应该调用 configureMock
方法,该方法将调用 ON_CALL
宏,为您的模拟设置默认操作。传递给 Invoke
的函数可以是与您要覆盖的方法的签名相匹配的任何函数。在这种情况下,它是一个函数,用于计算模拟已被调用的次数和 returns 适当的值。您还可以将某些特定对象分配给 msg
输出参数。
在代码 Google 模拟测试片段中有一个 EXPECT_CALL
return 是 True 和一个参数引用 200 次。
怎么才能让测试每n次都return为真呢。例如,每 10 次调用 return True,否则 return False。
class MockHandler : public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
}
TEST(TestDispatcher, HandlePing)
{
auto mockedHandler = make_unique<MockHandler>();
Msg rxMsg = { REQUEST::REQ_PING, sizeof(DefaultMsg_t), rxMsg.rx,(uint8_t*)"0"};
EXPECT_CALL(*mockedHandler,
RxMsg(_)).Times(checkValue).WillRepeatedly(
DoAll(SetArgReferee<0>(rxMsg), Return(TRUE)));
Dispatcher dispatcher(10, mockedHandler);
for (int i = 0; i < 199; i++)
{
dispatcher.RunToCompletion();
}
}
可能适合您的方法很少。我喜欢将 Invoke
作为默认操作的解决方案,因为它是最灵活的。您没有在问题中提供 mcve,所以我为您使用的 类 编写了非常简单的实现。此外,您使用 unique_ptr
作为模拟也犯了一个错误。在 99% 的情况下必须 shared_ptr
,因为您在测试环境和被测系统之间共享它。
class Msg {};
class Handler {
public:
virtual bool RxMsg(Msg &msg) = 0;
};
class MockHandler: public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
};
class Dispatcher {
public:
Dispatcher(std::shared_ptr<Handler> handler): h_(handler) {}
void run() {
Msg m;
std::cout << h_->RxMsg(m) << std::endl;
}
private:
std::shared_ptr<Handler> h_;
};
class MyFixture: public ::testing::Test {
protected:
MyFixture(): mockCallCounter_(0) {
mockHandler_.reset(new MockHandler);
sut_.reset(new Dispatcher(mockHandler_));
}
void configureMock(int period) {
ON_CALL(*mockHandler_, RxMsg(_)).WillByDefault(Invoke(
[this, period](Msg &msg) {
// you can also set the output arg here
// msg = something;
if ((mockCallCounter_++ % period) == 0) {
return true;
}
return false;
}));
}
int mockCallCounter_;
std::shared_ptr<MockHandler> mockHandler_;
std::unique_ptr<Dispatcher> sut_;
};
TEST_F(MyFixture, HandlePing) {
configureMock(10);
for (int i = 0; i < 199; i++) {
sut_->run();
}
}
在每次测试开始时,您应该调用 configureMock
方法,该方法将调用 ON_CALL
宏,为您的模拟设置默认操作。传递给 Invoke
的函数可以是与您要覆盖的方法的签名相匹配的任何函数。在这种情况下,它是一个函数,用于计算模拟已被调用的次数和 returns 适当的值。您还可以将某些特定对象分配给 msg
输出参数。