Google suggests delegating calls to a parent object when you need to invoke functionality of the real object, however this does not really create a partial (hybrid) mock. When invoking the real object, any method calls are those of the real object and not the mock object, on which you may have set up actions/expectations. How do I create a partial mock that delegates only specific methods to the real object, and all other method calls to the mock object?
Delegate to real object example
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;
class MockFoo : public Foo {
public:
MockFoo() {
// By default, all calls are delegated to the real object.
ON_CALL(*this, DoThis())
.WillByDefault(Invoke(&real_, &Foo::DoThis));
ON_CALL(*this, DoThat(_))
.WillByDefault(Invoke(&real_, &Foo::DoThat));
...
}
MOCK_METHOD0(DoThis, ...);
MOCK_METHOD1(DoThat, ...);
...
private:
Foo real_;
};
...
MockFoo mock;
EXPECT_CALL(mock, DoThis())
.Times(3);
EXPECT_CALL(mock, DoThat("Hi"))
.Times(AtLeast(1));
... use mock in test ...
Instead of creating an instance of the real object as a member variable, the mock should simply extend the real object, then delegate all calls to the parent by default. You can now setup your mock like normal; setting a new ON_CALL will override the default call to the parent. We let polymorphism do the work for us -- all calls, even from the parent (real) object, invoke the mock object, then the ON_CALL statement was set to invoke either the parent object or the mock behavior. We have successfully mixed real object behavior with mock behavior. This is exactly the same as delegating calls to a parent class.
Delegate to parent class example
class Foo {
public:
virtual ~Foo();
virtual void Pure(int n) = 0;
virtual int Concrete(const char* str) { ... }
};
class MockFoo : public Foo {
public:
// Mocking a pure method.
MOCK_METHOD1(Pure, void(int n));
// Mocking a concrete method. Foo::Concrete() is shadowed.
MOCK_METHOD1(Concrete, int(const char* str));
// Use this to call Concrete() defined in Foo.
int FooConcrete(const char* str) { return Foo::Concrete(str); }
};
using ::testing::Invoke;
// Create mock instance foo.
...
// Delegate to parent.
ON_CALL(foo, Concrete(_))
.WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
The only downside to this technique is that it requires a lot of boilerplate code and is sensitive to code changes. I have extended googlemock to ease this process; the code is available here. It will generate partial mocks that call the parent (real) object by default for all methods, and generate matching constructors that pass arguments to the parent constructor.
The official Google Mock guideline and also the last proposal do work however introduce a lot of boilerplate code.
So here is my proposal:
Foo.h
class Foo {
public:
virtual ~Foo();
virtual void Pure(int n) = 0;
virtual int Concrete(const char* str) { ... }
};
MockFoo.h
class MockFoo: public Foo {
using Real = Foo;
public:
MockFoo();
virtual ~MockFoo();
MOCK_METHOD1(Pure, void(int n));
MOCK_METHOD1(Concrete, int(const char* str));
};
MockFoo.cpp
MockFoo::MockFoo() {
using ::testing::Invoke;
ON_CALL(*this, Pure()).WillByDefault(Invoke([this] {return Real::Pure();}));
ON_CALL(*this, Concrete()).WillByDefault(Invoke([this] {return Real::Concrete();}));
};
MockFoo::~MockFoo() = default;
It's worth noting that having an implementation file for the mock is a good practice with observable benefits for test compilation time. Nice and easy.
Related
the normal pattern of gmock testing is
class MyMockClass : public MyRealClass {
/// swap out behavior of an existng method
MOCK_method(some_method .....);
}
TEST() {
MyMockClass mock;
EXPECT_CALLED(mock.some_method);
/// ******* here I have to explicitly pass in the mock obj into the system
MyConsumerClass myconsumer(mock);
myconsumer.do_something_to_trigger_mock__some_method();
}
in the above "****" line I have to explicitly pass in a mock obj into the system, i.e. compose my consumer obj with a mock obj. But now I face an existing consumer class impl, its constructor does not allow passing in the dependency objects; in fact I can probably argue that it's impossible to list all the dependency objects in the ctor of a consumer class; more importantly, my real case is that the consumer class to be tested sits several levels above the mock obj:
class MyConsumerClass {
private:
MyHelperClass helper
public:
void trigger() {
helper.trigger_again();
}
}
class MyHelperClass {
BottomClass bottom;
public:
void trigger_again() {
bottom.do_something();
}
}
class BottomClass {
public :
void do_something();
}
in this case, in our unit test, we can only instantiate the top level MyConsumerClass, and I was hoping to verify that when I call myconsumer.trigger(), I could verify that the BottomClass.do_something() is called, possibly also verifying that it's called with a specific argument. But the above class hierarchy is written so that I can not pass in a mock BottomClass obj from the top level.
in jmock or jmockit, I remember it's possible to globally wipe out the behavior of BottomClass.do_something(), without referring to a specific mock obj, i.e. "static mocking", as they are called in jmockit. is it possible to do something like that in gmock (c++)? thanks
Converting the comment to an answer:
I can think of two things:
Why don't you test your classes separately? For example, write a separate test for MyHelperClass.
If dependency injection doesn't work for you, GMock allows you to do static mocking by templatizing your classes: Convert your classes to templates, then instantiate the template with real classes for production and with mock classes for testing. See here for an example.
In your case, your code could be rewritten to something like this:
//-----------------------------------------------------------------------------
// Real classes used in production
//-----------------------------------------------------------------------------
class BottomClass {
public:
void do_something();
};
//-----------------------------------------------------------------------------
// Templatized classes used in test or production
//-----------------------------------------------------------------------------
template <class BType>
class MyHelperClass {
public:
BType bottom;
public:
void trigger_again() { bottom.do_something(); }
};
template <class BType, template <typename> class HType>
class MyConsumerClass {
public:
HType<BType> helper;
public:
void trigger() { helper.trigger_again(); }
};
//-----------------------------------------------------------------------------
// Mocked classes used in test
//-----------------------------------------------------------------------------
class MockedBottomClass {
public:
MOCK_METHOD(void, do_something, (), ());
};
TEST(BottomClassTest, Test1) {
MyConsumerClass<MockedBottomClass, MyHelperClass> mock;
EXPECT_CALL(mock.helper.bottom, do_something());
mock.trigger();
}
I had to convert some of your private members to public members for the test to work.
Live example here: https://godbolt.org/z/qc3chdxKz
I have a library class that I need to mock in one of my tests, and the object that accepts it takes a unique_ptr to one. After reading this answer, I assumed I could just do something like this.
class LibraryClassMock : public LibraryClass {
public:
MOCK_METHOD0(do, void());
};
TEST(ProxyServiceTest, RequestMade) {
auto mock = std::make_unique<LibraryClassMock>();
auto mockPtr = mock.get();
// Setup mock
EXPECT_CALL(*mockPtr, do()).Times(1);
// Signature of constructor is MySerivce(std::unique_ptr<LibraryClass>)
MyService service{std::move(mock)};
proxyService.runCommand("cmd");
}
Unfortunately, LibraryClass does not have a virtual destructor (nor can I add one), and because MyService holds a pointer of the form unique_ptr<LibraryClass>, this scope ending causes a leak (as the mock's destructor is not called). Without reworking Service to accept a shared_ptr, is there a way to work around this? In my application, service should be controlling the lifetime of the object passed in, but I need to mock it for my test.
You could introduce some stub classes and wrapper that don't need a destructor. Then you put the g-mock methods on the stub class.
class TestLibraryClass {
public:
virtual void do() {};
}
class LibraryClassMock : public TestLibraryClass {
public:
MOCK_METHOD0(do, void());
};
class LibraryClassMockWrapper : public LibraryClass {
public:
LibraryClassMock* pMock;
void do() override {
pMock->do();
}
};
TEST(ProxyServiceTest, RequestMade) {
auto mock = new LibraryClassMock();
// Setup mock
EXPECT_CALL(mock, do()).Times(1);
// setup unique_ptr
std::unique_ptr<LibraryClass> upWrapper(new LibraryClassMockWrapper()); // upWrapper owns mockWrapper lifetime, but not mock
upWrapper->pMock = mock;
// Signature of constructor is MySerivce(std::unique_ptr<LibraryClass>)
MyService service{std::move(upWrapper)};
proxyService.runCommand("cmd");
delete mock;
}
I want to define for a mocked method the behavior that when it is called in a test, all the EXPECTED_CALL and ON_CALL specific for that test are being checked, but still the original method is being executed after that.
You can accomplish this by using the delegating-to-real technique, as per Google Mock documentation:
You can use the delegating-to-real technique to ensure that your mock has the same behavior as the real object while retaining the ability to validate calls. Here's an example:
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;
class MockFoo : public Foo {
public:
MockFoo() {
// By default, all calls are delegated to the real object.
ON_CALL(*this, DoThis())
.WillByDefault(Invoke(&real_, &Foo::DoThis));
ON_CALL(*this, DoThat(_))
.WillByDefault(Invoke(&real_, &Foo::DoThat));
...
}
MOCK_METHOD0(DoThis, ...);
MOCK_METHOD1(DoThat, ...);
...
private:
Foo real_;
};
...
MockFoo mock;
EXPECT_CALL(mock, DoThis())
.Times(3);
EXPECT_CALL(mock, DoThat("Hi"))
.Times(AtLeast(1));
... use mock in test ...
Is it possible to make a mock class copiable in Google Test Framework?
I've seen that the default copy constructor and copy assignment operator are deleted once that the MOCK_METHOD macros are used.
Is there a way to workaround that?
I cannot imagine any use case for copying mock objects. When you want to mimic real object with mock object - you shall have access to the very same object from code under test and from your test case code - so why copying needed?
Anyway - I see one method to make copying of mock object:
You have to define wrapper on mock object - which shall be kept by std::shared_ptr.
An example:
class XxxMock : public XxxInterface
{
public:
MOCK_METHOD0(foo, void());
};
#include <memory>
class XxxSharedMock : public XxxInteface
{
public:
XxxSharedMock(std::shared_ptr<XxxMock> xxxMock = std::make_shared<XxxMock>())
: xxxMock(xxxMock)
{}
void foo() override
{
xxxMock->foo();
}
// having: XxxSharedMock xxxMock;
// do: EXPECT_CALL(xxxMock.mock(), foo());
XxxMock& mock() { return *xxxMock; }
XxxMock const& mock() const { return *xxxMock; }
privated:
std::shared_ptr<XxxMock> xxxMock;
};
I have 2 classes.
class SomeClass
{
public:
int SomeFunction()
{
return 5;
}
};
class AnotherClass
{
public:
int AnotherFunction(SomeClass obj)
{
return obj.SomeFunction();
}
};
I have made a mock class for SomeClass.
class MockSomeClass : public SomeClass
{
public:
MOCK_METHOD0(SomeFunction, int());
};
Now I want in unit test that when i call AnotherClass.AnotherFunction i get result of my own choice. AnotherFunction uses function of SomeClass.SomeFunction(). I have mocked SomeClass. And I have set that when function of mocked object calls it returs 10. But when i run unit test it returns 5 (origional function). What should i do. Below is the unit test which i have written.
[TestMethod]
void TestMethod1()
{
MockSomeClass mock;
int expected = 10;
ON_CALL(mock, SomeFunction()).WillByDefault(Return(expected));
AnotherClass realClass;
int actual = realClass.AnotherFunction(mock);
Assert::AreEqual(expected, actual);
};
I am using visual studio 2008 and gmock 1.6.0. What is wrong I am doing. on realClass.AnotherFunction i want mocked output from mock.SomeFunction().
The problem is that SomeClass::SomeFunction(...) isn't virtual, make it virtual and it will work.
Update:
There is one more fundamental error that causes it to fail, that is the method signature of
int AnotherFunction(SomeClass obj)
which creates a new SomeClass object instance which will in it's turn cause the normal SomeFunction to be called, you should instead pass a reference to the mocked class as argument.
int AnotherFunction(SomeClass* obj)
and invoke it using
int actual = realClass.AnotherFunction(&mock);