使用 Gmock 模拟重载方法

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

问候,所以我有一个如下所示的界面

class AInterface {
public:
    /// The different states the =A can be in
    enum class State {
        IDLE,
        BUSY
    };

    
    struct AMetadata {
    /**
     * Default constructor
     */
    AMetadata() = default;

    AMetadata(State state)
    : state(state){}


    State state = State::IDLE;
    };

    /// Destructor.
    virtual ~AInterface() = default;

    virtual void onStateChanged(State state){}; // deprecated but still have to be here
    virtual void onStateChanged(const AMetadata& metadata){}; // i am adding this method
};

我的模拟课是这样定义的

class MockObserver : public AInterface {
public:
    MOCK_METHOD1(onStateChanged, void(State state));
    MOCK_METHOD1(onStateChanged, void(const AMetadata& metadata));
};


// arg is passed to the matcher implicitly
// arg is the actual argument that the function was called with
MATCHER_P(AMetadataMatcher, expectedMetadata, "") {
    return arg.state == expectedMetadata.state;
}

基本上在测试代码中,实现看起来像这样,其中先前的 arg 是 State 但现在 arg 必须是 AMetadata

EXPECT_CALL(*m_mockObserver, onStateChanged(_)).Times(AnyNumber());

EXPECT_CALL(*m_mockObserver, onStateChanged(AInterface::State::BUSY))
            .WillOnce(Invoke([&](AMetadata metadata) {
                EXPECT_EQ(...,...);
            }));
EXPECT_CALL(*m_mockObserver, onStateChanged(AInterface::State::IDLE))
            .WillOnce(Invoke([&](AMetadata metadata) {
                EXPECT_EQ(...,...);
            }));

按原样编译显然我得到编译错误

ATest.cpp:: error: call to member function 'gmock_onStateChanged' is ambiguous
    EXPECT_CALL(*m_mockObserver, onStateChanged(_).Times(AnyNumber()));

我尝试了 ::testing::TypedEq 和 ::testing::An 如下所示,我仍然遇到编译错误

EXPECT_CALL(*m_mockObserver, onStateChanged(::testing::TypedEq<const AMetadata&>(_))).Times(AnyNumber());

ATest.cpp:1288:49: 错误:没有匹配函数来调用“TypedEq” EXPECT_CALL(*m_mockObserver, onStateChanged(::testing::TypedEq())).Times(AnyNumber());

我什至尝试过像自定义匹配器这样的东西

AMetadata metadata;
metadata.state = IDLE;
EXPECT_CALL(*m_mockObserver, onStateChanged(AMatcher<const AMetadata&>(metadata)).Times(AnyNumber()));

但我仍然遇到错误,所以我不确定在 gmock 中使用重载函数的最佳方法是什么,基本上我需要编写调用,其中 expect 调用需要在结构内的值上工作,而我所处的情况不是只有重载方法具有相同的名称和相同数量的争论,任何指导或代码片段将不胜感激。

c++ unit-testing overloading googletest googlemock
1个回答
0
投票

您可以在 google 测试文档中使用这个提供的解决方案

在重载函数之间进行选择

如果您希望调用重载函数,编译器可能需要一些帮助来确定它是哪个重载版本。

要消除在此对象的常量性上重载的函数的歧义,请使用 Const() 参数包装器。 使用 ::testing::ReturnRef;

class MockFoo : public Foo {
  ...
  MOCK_METHOD(Bar&, GetBar, (), (override));
  MOCK_METHOD(const Bar&, GetBar, (), (const, override));
};

...
  MockFoo foo;
  Bar bar1, bar2;
  EXPECT_CALL(foo, GetBar())         // The non-const GetBar().
      .WillOnce(ReturnRef(bar1));
  EXPECT_CALL(Const(foo), GetBar())  // The const GetBar().
      .WillOnce(ReturnRef(bar2));

(Const() 由 gMock 定义并返回对其参数的 const 引用。)

要消除参数数量相同但参数类型不同的重载函数的歧义,您可能需要指定匹配器的确切类型,方法是将匹配器包装在 Matcher() 中,或者使用类型固定的匹配器(TypedEq,An (), 等):

using ::testing::An;
using ::testing::Matcher;
using ::testing::TypedEq;

class MockPrinter : public Printer {
 public:
  MOCK_METHOD(void, Print, (int n), (override));
  MOCK_METHOD(void, Print, (char c), (override));
};

TEST(PrinterTest, Print) {
  MockPrinter printer;

  EXPECT_CALL(printer, Print(An<int>()));            // void Print(int);
  EXPECT_CALL(printer, Print(Matcher<int>(Lt(5))));  // void Print(int);
  EXPECT_CALL(printer, Print(TypedEq<char>('a')));   // void Print(char);

  printer.Print(3);
  printer.Print(6);
  printer.Print('a');
}

我希望这会有所帮助

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