Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GMock - returning default value with ON_CALL for overloaded methods

Tags:

c++

gmock

I'm trying to write mock for a class which contains three overloaded methods, ie.:

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

using ::testing::_;
using ::testing::Return;
using ::testing::A;
using ::testing::ByRef;
using ::testing::Ref;
using ::testing::TypedEq;

struct Foo {
  int fooMethod(const int& intParam) { return 0; }
  int fooMethod(const float& floatParam) { return 0; }
  int fooMethod(const std::string& stringParam) { return 0; }
};

struct FooMock {
  FooMock() {
    ON_CALL(*this, fooMethod(_)).WillByDefault(Return(-1));
  }

  MOCK_METHOD1(fooMethod, int(const int& intParam));
  MOCK_METHOD1(fooMethod, int(const float& floatParam));
  MOCK_METHOD1(fooMethod, int(const std::string& stringParam));
};

but this gives an error:

 error: call of overloaded ‘gmock_fooMethod(const testing::internal::AnythingMatcher&)’ is ambiguous

I've also tried TypedEq() instead of "_", but it gives more obscure errors. I've checked GMock FAQ, Wiki and I didn't find solution - how can I return default value with ON_CALL for overloaded methods?

BR, Lukasz

like image 971
lgromanowski Avatar asked May 10 '13 10:05

lgromanowski


2 Answers

@tx34 has the crux of the answer, but there are a few more issues in the code.

Firstly, the docs on Selecting Between Overloaded Functions are most appropriate. You have three overloads of fooMethod with the same number of arguments but different argument types. You're going to have to use a matcher that specifies the type.

Next, you need to define all your Foo functions which are to be mocked as virtual, or else invoking them through a Foo object won't call the derived mock functions. Since you're defining Foo as a base class, it should also have a virtual destructor to avoid slicing.

Finally, you need to have FooMock inherit from Foo.

So putting it all together, you end up with something like:

#include <memory>
#include <string>
#include "gtest/gtest.h"
#include "gmock/gmock.h"

using ::testing::_;
using ::testing::An;
using ::testing::Matcher;
using ::testing::TypedEq;
using ::testing::Return;

struct Foo {
  virtual ~Foo() {}
  virtual int fooMethod(const int&) { return 0; }
  virtual int fooMethod(const float&) { return 0; }
  virtual int fooMethod(const std::string&) { return 0; }
};

struct FooMock : Foo {
  FooMock() : Foo() {
    ON_CALL(*this, fooMethod(An<const int&>())).
        WillByDefault(Return(-1));
    ON_CALL(*this, fooMethod(Matcher<const float&>(_))).
        WillByDefault(Return(-2));
    ON_CALL(*this, fooMethod(TypedEq<const std::string&>("1"))).
        WillByDefault(Return(-3));
  }

  MOCK_METHOD1(fooMethod, int(const int& intParam));
  MOCK_METHOD1(fooMethod, int(const float& floatParam));
  MOCK_METHOD1(fooMethod, int(const std::string& stringParam));
};

TEST(Foo, foo) {
  std::shared_ptr<Foo> foo(new FooMock);
  auto foo_mock(std::dynamic_pointer_cast<FooMock>(foo));

  EXPECT_CALL(*foo_mock, fooMethod(Matcher<const int&>(_))).Times(1);
  EXPECT_CALL(*foo_mock, fooMethod(Matcher<const float&>(_))).Times(1);
  EXPECT_CALL(*foo_mock, fooMethod(Matcher<const std::string&>(_))).Times(1);

  EXPECT_EQ(-1, foo->fooMethod(1));
  EXPECT_EQ(-2, foo->fooMethod(1.0f));
  EXPECT_EQ(-3, foo->fooMethod("1"));
}


int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
like image 132
Fraser Avatar answered Sep 26 '22 06:09

Fraser


The problem is TypedEq expects a value not a matcher. You can achieve what you want by:

ON_CALL(*this, fooMethod(An<ArgType>())).WillByDefault(Return(-1));

or

ON_CALL(*this, fooMethod(Matcher<ArgType>(_))).WillByDefault(Return(-1));

See also:

https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md#selecting-between-overloaded-functions-selectoverload

https://github.com/google/googletest/blob/master/docs/gmock_cheat_sheet.md#wildcard

https://github.com/google/googletest/blob/master/docs/gmock_cheat_sheet.md#generic-comparison

like image 22
tx34 Avatar answered Sep 23 '22 06:09

tx34