如何基于参数动态设置Mock方法的EXPECT_CALL期望?
问题:如何动态设置Google Mock方法的调用期望?
我编写了一个测试,当前通过以下静态方式设置Mock方法的调用期望,代码可正常运行且测试通过:
EXPECT_CALL(*iter, NextBatch(_, _)) .WillOnce(Invoke(MakeMockNextBatchCb( responses[0] /* values */, batch_size, at_end))) .WillOnce(Invoke(MakeMockNextBatchCb( responses[1] /* values */, batch_size, at_end))) .WillOnce(Invoke(MakeMockNextBatchCb( responses[2] /* values */, batch_size, at_end)));
其中responses是一个存储响应数据的vector。
但我需要编写参数化测试,因此要改为动态实现的版本。尝试用for循环逐个设置期望的方案无效(原因是每个独立的EXPECT_CALL会产生冲突,无法按顺序匹配多次调用):
for(int i=0; i<responses.size(); ++i) { EXPECT_CALL(*iter, NextBatch(_, _)) .WillOnce(Invoke(MakeMockNextBatchCb( responses[i] /* values */, batch_size, at_end))); }
希望实现类似上述循环的写法,同时具备最初静态代码的功能,请问该如何动态设置Mock方法的调用期望?
解决方案
方法1:动态构建链式WillOnce调用
核心思路是先创建一个EXPECT_CALL对象,再在循环中向该对象逐次追加WillOnce动作,效果与静态链式写法完全一致:
// 初始化期望对象,后续循环追加动作 auto& mock_call = EXPECT_CALL(*iter, NextBatch(_, _)); for (const auto& resp : responses) { mock_call.WillOnce(Invoke(MakeMockNextBatchCb(resp, batch_size, at_end))); }
这种方式会让NextBatch方法按顺序依次返回responses中每个元素对应的响应,完全匹配最初静态代码的逻辑。
方法2:用WillRepeatedly配合计数器
如果需要更灵活的控制逻辑,可以通过计数器遍历responses,结合WillRepeatedly实现动态响应:
int call_count = 0; EXPECT_CALL(*iter, NextBatch(_, _)) // 指定调用次数,避免超出vector下标范围 .Times(responses.size()) .WillRepeatedly(Invoke([&](/* 需匹配NextBatch的实际参数类型 */ auto&&... args) { auto callback = MakeMockNextBatchCb(responses[call_count], batch_size, at_end); call_count++; // 传递参数并执行回调 return callback(std::forward<decltype(args)>(args)...); }));
注意:需根据NextBatch方法的实际参数类型调整lambda的参数列表,确保类型匹配。
方法3:序列控制约束调用顺序(可选)
如果需要严格保证调用顺序,可以结合Google Mock的Sequence机制:
testing::Sequence seq; for (const auto& resp : responses) { EXPECT_CALL(*iter, NextBatch(_, _)) .InSequence(seq) .WillOnce(Invoke(MakeMockNextBatchCb(resp, batch_size, at_end))); }
这种方式通过Sequence强制要求调用按循环顺序匹配,适合对调用顺序有严格要求的测试场景。
内容的提问来源于stack exchange,提问作者Aman Deep Gautam
相关产品推荐
相关产品推荐

