roschach
roschach

Reputation: 9396

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?

Upvotes: 0

Views: 120

Answers (1)

pptaszni
pptaszni

Reputation: 8312

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.

Upvotes: 1

Related Questions