Search code examples
c++mockinggoogletestoverload-resolutiongooglemock

While mocking with googletest, how to specify the argument type of an internal::AnythingMatcher for overloaded methods?


initial question

While testing with googletest, I use a mocked class, which contains an overloaded method, where one of the arguments differs in type.

This leads to an ambiguous function call when I do

EXPECT_CALL(mockedClass,mockedMethod(_,_)).WillOnce(Return(true));

I tried to combine the internal::AnythingMatcher underscore with a type specification by replacing the argument in question with An<type>(), TypedEq<type>(_), or Matcher<type>(_) as well as writing something like:

Matcher<type> customAnythingMatcher = _;
EXPECT_CALL(mockedClass,mockedMethod(_,customAnythingMatcher)).WillOnce(Return(true));

all to no avail. Any hints how to disambiguate that call?

update #1

As requested, I elaborate by providing a minimal working -- or in this case a non-working -- example what I am trying to achieve:

myInterfaceToMock.h

#ifndef MYINTERFACETOMOCK_H
#define MYINTERFACETOMOCK_H

#include <QVariant>
#include <QtGlobal>
class MyInterfaceToMock {
  virtual bool myMethod(QVariant &firstArgument,
                        const quint8 secondArgument) const = 0;
  virtual bool myMethod(QByteArray &firstArgument,
                        const quint16 secondArgument) const = 0;
  virtual bool myOtherMethod(quint8 firstAndOnlyArgument) const = 0;
};

#endif  // MYINTERFACETOMOCK_H

myMock.h

#ifndef MYMOCK_H
#define MYMOCK_H

#include <gmock/gmock.h>

#include <QtCore/QObject>

#include "myInterfaceToMock.h"
class MyMock : public MyInterfaceToMock {
 public:
  // virtual bool myMethod(QVariant &firstArgument, const quint8 secondArgument)
  // const = 0;
  MOCK_METHOD(bool, myMethod, (QVariant &, const quint8), (const, override));
  // virtual bool myMethod(QByteArray &firstArgument, const quint16
  // secondArgument) const = 0;
  MOCK_METHOD(bool, myMethod, (QByteArray &, const quint16), (const, override));
  // virtual bool myOtherMethod(quint8 firstAndOnlyArgument) const = 0;
  MOCK_METHOD(bool, myOtherMethod, (quint8), (const, override));
};

#endif  // MYMOCK_H

main.cpp

#include <gmock/gmock-matchers.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <QCoreApplication>
#include <QTimer>

class Tester : public QObject {
  Q_OBJECT
 public:
  Tester(QObject *parent = nullptr) : QObject(parent) {}

 public slots:
  void run() {
    ::testing::InitGoogleTest();
    emit(result(RUN_ALL_TESTS()));
  }

 signals:
  void result(int res);
};

#include "main.moc"

int main(int argc, char *argv[]) {
  QCoreApplication app(argc, argv);

  ::testing::InitGoogleMock(&argc, argv);

  Tester *tester = new Tester(&app);

  QObject::connect(tester, &Tester::result, &app, &QCoreApplication::exit);

  QTimer::singleShot(0, tester, SLOT(run()));

  return app.exec();
}

#include "myMock.h"
TEST(myTest, testMockOverload) {
  using namespace testing;
  MyMock mock;
  // Reference method, which does work all the time
  EXPECT_CALL(mock, myOtherMethod(_)).WillRepeatedly(Return(false));
  // Using a defined value as argument
  QVariant myVariant;
  EXPECT_CALL(mock, myMethod(myVariant, 3)).WillOnce(Return(true));
  bool result = mock.myMethod(myVariant, 3);
  ASSERT_TRUE(result);
  // Anything matcher for the unambiguous argument
  EXPECT_CALL(mock, myMethod(myVariant, _)).WillOnce(Return(true));
  result = mock.myMethod(myVariant, 3);
  ASSERT_TRUE(result);
  // Trying to match any passed qvariant
  EXPECT_CALL(mock, myMethod(An<QVariant>(), _)).WillOnce(Return(true));
}

The compiler error is issued for the last line:

..\googlemock_disambiguate\main.cpp(55): error C2664: 'testing::internal::MockSpec<bool (QByteArray &,quint16)> MyMock::gmock_myMethod(const testing::internal::WithoutMatchers &,const testing::internal::Function<bool (QByteArray &,quint16)> *) const': cannot convert argument 1 from 'testing::Matcher<QVariant>' to 'const testing::Matcher<QVariant &> &'
..\googlemock_disambiguate\main.cpp(55): note: Reason: cannot convert from 'testing::Matcher<QVariant>' to 'const testing::Matcher<QVariant &>'
..\googlemock_disambiguate\main.cpp(55): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

I have a guess that it might have sth. to do with the constness of the method, but I still do not understand the meaning of that error...


Solution

  • Answering the question myself:

    I simply did not specify the type correctly, since I expect a reference to get passed. I always tried to use something like An<type>(), where I should have used An<type&>() instead.

    So, based on my above example, the correct line simply is:

    EXPECT_CALL(mock, myMethod(An<QVariant&>(), _)).WillOnce(Return(true));