c++overloadinggoogletestvtable

how to use ON_CALL and Matcher in gtest with overloaded mocked nfunctions?


I am mocking a class with two overloaded methods like this:

//required because some versions of gtest messes with extra commas in MOCK_METHOD
typedef std::pair<char*, uint32_t>  KeyValueType;
class MockSUT : public SUT
{
public:

    MOCK_METHOD(bool, foo, (const std::vector<KeyValueType> &data), (override));
 
    MOCK_METHOD(bool, foo, (const std::string &key, const std::string& data), (override));
};

In a test I am doing something like this (the code is not optimal but I am trying to understand what's going on and probably EXPECT_CALL is better here but I am trying to understand):

TEST_F(fixture, test)
{
  ...
  std::shared_ptr<Mocksut> mock = std::make_shared<MocksSUT>();
  ON_CALL(..,..); //on call on another mock that succeds

  ON_CALL(*mock.get(), foo(::testing::Matcher<const std::vector<std::pair<char*, uint32_t>>&>()))
      .WillByDefault([&](const std::vector<std::pair<char*, uint32_t>>& data)-> bool{
        EXPECT_TRUE(true);
        return true;
  });
}

where Matcher must be used apparently in overloading cases. Also I had to specify the return value of the lambda with ->bool.

The original function is called in this way:

shared_pointer_castom->foo({
  { 
    defined_char_array, 
    static_cast<uint32_t>(someVal)
  }, 
  { 
    defined_car_array2, 
    static_cast<uint32_t>(someOtherVal)
  }]
});

By debugging the code, I see it is running and the first MOCk_METHOD is correctly called. After that I get a null pointer exception in the gtest, precisely in /loki/loki-dev-env/Orin/01_linux64/include/gtest/gtest-matchers.h:269:: Condition vtable_ != nullptr failed. (it does not enter the ON_CALL lambda). The code is the following:

template <typename T>
class MatcherBase : private MatcherDescriberInterface {
 public:
  // Returns true if and only if the matcher matches x; also explains the
  // match result to 'listener'.
  bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
    GTEST_CHECK_(vtable_ != nullptr);
    return vtable_->match_and_explain(*this, x, listener);
  }
...

I guess I am not using correctly ON_CALL and Matcher. How to use ON_CALL together with Matcher to test an overloaded method?


Solution

  • According to gmock cookbook, testing::Matcher shall be used to wrap your matcher, e.g.:

    exact match of some testing data:

    std::vector<KeyValueType> testData;
    ON_CALL(mock, foo(testing::Matcher<const std::vector<std::pair<char*, uint32_t>>&>(testData)))
    

    testing for some elements presence:

    std::vector<KeyValueType> testData;
    char rawText[] = "xxx";
    auto pair1 = std::make_pair(rawText, uint32_t(69));
    testData.push_back(pair1);
    testData.push_back(pair1);
    ON_CALL(mock, foo(testing::Matcher<const std::vector<std::pair<char*, uint32_t>>&>(testing::Contains(pair1))))
    

    But if you simply want to disambiguate the call and you want to match against any value, you can simply use testing::An:

    ON_CALL(mock, foo(testing::An<const std::vector<std::pair<char*, uint32_t>>&>()))
    

    Finally, your example doesn't need any of those tricks, because your overloaded foo take different number of arguments, so simple:

    
    ON_CALL(mock, foo(testing::_))
        .WillByDefault([&](const auto& data) { // note, no need to explicitly specify args and return types
            EXPECT_TRUE(true);  // note, it's not a classic approach to expect things inside mock callbacks; better to test the observable effects
            return true;
        });
    

    is enough.

    Note: in my examples for simplicity I used MockSUT mock; and a trivial implementation of struct SUT.