如何将额外的参数传递给google模拟EXPECT_CALL

问题描述 投票:0回答:1

我正在测试通过接口使用依赖项的 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 ();
}
c++ googletest googlemock
1个回答
0
投票

不确定我是否正确理解了您的匹配器要求,但您的问题可以通过非常通用的方式解决。您可以在 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();

请告诉我我是否正确理解了您的要求。

© www.soinside.com 2019 - 2024. All rights reserved.