我正在测试通过接口使用依赖项的 C++ 类。我已经模拟了该接口,并在 GMock 的 EXPECT_CALL 中使用了一个复杂的 lambda,以验证我的类是否正确调用了模拟函数。在一次调用我的类的 API 期间,函数会被多次调用。不同的调用中正确的行为是不同的,所以我想在不同的调用中为我的检查器提供不同的预期结果。
如何在
EXPECT_CALL(..).WillOnce(lambda)
中为我的 lambda 给出不同的预期结果?
意思是这样的:
EXPECT_CALL(..)
.WillOnce(InvokeWithExtraArgs(lambda, expectedResult1)),
.WillOnce(InvokeWithExtraArgs(lambda, expectedResult2)),
完整示例:
#include "gtest/gtest.h"
#include "gmock/gmock.h"
using namespace testing;
struct Dependency
{
virtual void foo (double d) = 0;
};
struct DependencyMock : public Dependency
{
MOCK_METHOD (void, foo, (double), (override));
};
struct Service
{
Service (Dependency *d) : dep {d} {};
void doStuff ()
{
dep->foo (1.2);
dep->foo (2.3);
}
Dependency *dep;
};
TEST (mytest, test1)
{
DependencyMock depMock;
Service service {&depMock};
auto fooVerifier = [] (double d /*, int expectedResult - is this possible? */ )
{
auto result = d + 123; // some lengthy logic here to deduce if foo() was called correctly
auto expectedResult = 234; // <<< how to get this as an argument
EXPECT_EQ (result, expectedResult);
};
EXPECT_CALL (depMock, foo (_))
.Times(2)
.WillOnce (Invoke (fooVerifier)) // <<< How can I give expected result for above EXPECT_EQ here?
.WillOnce (Invoke (fooVerifier)); // <<< How can I give expected result for above EXPECT_EQ here?
service.doStuff ();
}
int main (int argc, char *argv[])
{
::testing::InitGoogleTest (&argc, argv);
return RUN_ALL_TESTS ();
}
不确定我是否正确理解了您的匹配器要求,但您的问题可以通过非常通用的方式解决。您可以在 EXPECT_CALL 操作上调用任何逻辑,因此:
TEST (mytest, test1)
{
DependencyMock depMock;
Service service {&depMock};
int scenarioCounter = 0; // can be std::atomic_int if your system would use some async operations
auto verifyResult1 = [] (double d) { return true; }; // impl your logic
auto verifyResult2 = [] (double d) { return true; }; // impl your logic
EXPECT_CALL(depMock, foo (_)).WillRepeatedly([&](double d) {
if (scenarioCounter == 0 && !verifyResult1(d)) {
throw std::runtime_error("explain what happened");
}
else if (scenarioCounter == 1 && !verifyResult2(d)) {
throw std::runtime_error("explain what happened again");
}
scenarioCounter++;
});
service.doStuff(); // ASSERT_NO_THROW if you prefer
}
仅配置 1 个 EXPECT_CALL (gmock 对具有不同参数的同一函数的期望不是很用户友好),并根据您当前的系统状态实现不同的验证操作。在示例中,我使用
scenarioCounter
来跟踪该状态。您可以抛出异常来立即退出并使测试用例失败,而不是 gtest 断言 - gtest 在测试周围有默认的 try-catch 块,因此它将解释测试失败的原因,但您也可以ASSERT_NO_THROW
。除了抛出,您还可以翻转一些布尔标志,或者简单地调用 FAIL();
。
请告诉我我是否正确理解了您的要求。