对 lambda 的模拟成员函数调用

Mock member function call to lambda

使用 c++17 和 gmock,我正在模拟 class 并希望将对其成员函数之一的调用重定向到 lambda。这可能吗?

他是一个最小的例子:

#include <gmock/gmock.h>

using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;

class Foo
{
public:
    virtual uint8_t MyCall(const uint8_t in) const
    {
        return in;
    }
};

class MockFoo : public Foo
{
public:
    MOCK_METHOD(uint8_t, MyCall, (const uint8_t), (const, override));
};

TEST(MyTest, MyTestCase)
{
    MockFoo mock_foo;
    ON_CALL(mock_foo, MyCall(_)).WillByDefault(Invoke([](const uint8_t to) {
        static_cast<void>(to);
    }));
}

编译时出现以下错误:

demo.cpp: In member function 'virtual void MyTest_MyTestCase_Test::TestBody()':
demo.cpp:82:7: error: no matching function for call to 'testing::internal::OnCallSpec<unsigned char(unsigned char)>::WillByDefault(std::decay<MyTest_MyTestCase_Test::TestBody()::<lambda(uint8_t)> >::type)'
     }));
       ^
In file included from external/gtest/googlemock/include/gmock/gmock-function-mocker.h:42:0,
                 from external/gtest/googlemock/include/gmock/gmock.h:61,
                 from demo.cpp:2:
external/gtest/googlemock/include/gmock/gmock-spec-builders.h:323:15: note: candidate: testing::internal::OnCallSpec<F>& testing::internal::OnCallSpec<F>::WillByDefault(const testing::Action<F>&) [with F = unsigned char(unsigned char)]
   OnCallSpec& WillByDefault(const Action<F>& action) {
               ^~~~~~~~~~~~~
external/gtest/googlemock/include/gmock/gmock-spec-builders.h:323:15: note:   no known conversion for argument 1 from 'std::decay<MyTest_MyTestCase_Test::TestBody()::<lambda(uint8_t)> >::type {aka MyTest_MyTestCase_Test::TestBody()::<lambda(uint8_t)>}' to 'const testing::Action<unsigned char(unsigned char)>&

你的 lambda 的 return 类型与你的成员函数不匹配

gmock 的错误消息可能有些晦涩难懂,当您使用基本类型的 typedef 类型时,它无济于事;在这种情况下 uint8_t.

如果我们仔细查看错误消息:

error: no matching function for call to

'testing::internal::OnCallSpec<unsigned char(unsigned char)>
    ::WillByDefault(std::decay<MyTest_MyTestCase_Test::TestBody()
        ::<lambda(uint8_t)> >::type)'

它实际上提供了一些提示:

  • unsigned char(unsigned char)
  • OnCallSpec
  • 与提供的 (WillByDefault) 可调用类型不匹配。

前者,当查看您的程序并在固定宽度的 typedef 中手动翻译时,实际上告诉我们:

  • uint8_t(uint8_t)
  • OnCallSpec

这使得默认可调用类型(即 lambda)的问题更加明显。

在这种特殊情况下,lambda 的 return 类型(隐含地)是 void,因此(忽略 CV 限定符)void(uint8_t) 与 "on call spec" uint8_t(uint8_t).