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;
};
Related
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 have the following object that I want to mock:
class Esc {
public:
Esc() = default;
virtual ~Esc() {}
virtual int GetMaxPulseDurationInMicroSeconds() const noexcept{
return 100;
}
};
I wrote this mock:
class MockEsc : public Esc {
public:
MockEsc(){}
MockEsc(const MockEsc&){}
MOCK_METHOD(int, GetMaxPulseDurationInMicroSeconds, (), (const, noexcept, override));
};
And this is the unit under test which calls the aforementioned Esc.GetMaxPulseDurationInMicroSeconds() method
class LeTodar2204{
public:
LeTodar2204() = delete;
explicit LeTodar2204(std::unique_ptr<Esc> esc) : esc_(std::move(esc)){}
int CallingMethod(){
int a = esc_->GetMaxPulseDurationInMicroSeconds();
return a;
}
private:
std::unique_ptr<Esc> esc_;
In the SetUp of my testfixture I want to set my mock to return a 1 and inject it into the unit under test.
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<propulsion::LeTodar2204>(std::make_unique<MockEsc>(esc_));
}
MockEsc esc_;
std::unique_ptr<propulsion::LeTodar2204> unit_under_test_;
};
Now in the test I call the method that should call the mocked method, but GetMaxPulseDurationInMicroSeconds of my mocked object only returns 0 (aka the default value) and warns me about the uninteresting function call.
This is the test
TEST_F(Letodar2204Tests, get_pulse_duration) {
EXPECT_CALL(esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
auto duration = unit_under_test_->CallingMethod();
ASSERT_EQ(duration, 1);
}
What am I missing?
Because you are effectively assigning expectation to an object which you'll be copying anyway. esc_ default ctor is going to be called once Letodar2204Tests is instantiated. Now, in SetUp you assign an expectation on class' field esc_, and then, basing on esc_ create a brand new object (on the heap, using make_unique) using its copy-ctor. Expectations are not going to be magically copied as well. I believe you should store an unique_ptr<MockEsc> esc_ as a class' field, instantiate it on heap within SetUp and inject to LeTodar:
class Letodar2204Tests : public ::testing::Test {
protected:
Letodar2204Tests() {}
virtual void SetUp() {
esc_ = std::make_unique<MockEsc>();
EXPECT_CALL(*esc_, GetMaxPulseDurationInMicroSeconds()).WillOnce(::testing::Return(1));
unit_under_test_ = std::make_unique<propulsion::LeTodar2204>(esc_);
}
std::unique_ptr<MockEsc> esc_;
std::unique_ptr<propulsion::LeTodar2204> unit_under_test_;
};
Here, you are implicitly calling copy-ctor: std::make_unique<MockEsc>(esc_)
You could do a simple test: mark copy ctor in MockEsc 'deleted' and you'll see that your project no longer compiles (at least it shouldn't be :D)
I have a test fixture in my tests so I don't have to instantiate objects of my class repeatedly, but I'm not sure how to use mocks with it. To put it simply, this is how the class is defined:
class Class1 {
public:
Class1(std::shared_ptr<Class2> class_two);
void doThisThing() { doThatThing(); }
}
class Class2 {
public:
Class2(Class3* class3_ptr);
int doThatThing();
}
(class 1 is constructed using a shared pointer to class 2. Class 2 is constructed with a pointer to class 3. Class 1 calls on a function "doThisThing" which calls Class 2's function doThatThing.)
I need to create a mock for doThatThing() (and the rest of Class2's functions), but can't figure out how to pass the mock object to Class 1. Here is what I have so far in my testing code:
class TestClass1 : public ::testing::Test {
TestClass1(){
//Construct instance of Class1 and store as member variable
std::shared_ptr<Class3> class_three = std::make_shared<Class3>();
std::shared_ptr<Class2> class_two = std::make_shared<Class2>((Class3*)class_three.get());
class_one = new Class1(class_two);
};
Class1* class_one;
}
MockClass2 : public Class2 {
MOCK_METHOD0(doThatThing, int());
}
TEST_F(TestClass1, doThatThingTest){
MockClass2 mockObj;
**THIS IS WHERE I'M STUCK. How do I get that mockObj into my TestClass1 Fixture? As of now, it is calling the actual function, not the mock***
class_one->doThatThing();
EXPECT_CALL(mockObj, doThatThing());
}
I had to abstract and simplify the actual code, so I hope the above makes sense.
Assuming that your MockClass2 works, you should try something like the following:
Here you should override the functions SetUp that is called right before every call of a test function to prepare your test data. And override TearDown that is called after every call of a test function to clean up test data.
struct TestClass1 : public ::testing::Test
{
void SetUp() override
{
class_two_mock = std::make_shared<MockClass2>();
class_one = std::make_unique<Class1>(class_two_mock);
}
void TearDown() override
{
class_one.reset();
class_two_mock.reset();
}
std::shared_ptr<MockClass2> class_two_mock
std::unique_ptr<Class1> class_one;
};
In the test function you must declare your expectations before something is executed.
TEST_F(TestClass1, doThatThingTest)
{
EXPECT_CALL(*class_two_mock, doThatThing());
class_one->doThatThing();
}
You may need an interface for Class2. The code here is not tested.
I want to unit test a class that looks like this:
template <typename T>
class MyClass {
...
void someMethod() {
T object;
object.doSomething();
}
...
};
I want to unit test this class, so I create a mock class for T:
struct MockT {
...
MOCK_METHOD(doSomething, 0, void());
...
};
Then I want to use it in a test case:
BOOST_AUTO_TEST_CASE(testSomeMethod) {
MyClass<MockT> myClassUnderTest;
MOCK_EXPECT(???)....;
myClassUnderTest.someMethod();
}
How do I make an expectation for this object? My first idea was to store all created MockT instances in a static container from the constructor, then delete them from the container from the destructor. This would work if the object were created in a different method than where it is used, like this:
myClassUnderTest.createTheObject();
MOCK_EXPECT(MockT::findMyObject().doSomething);
myClassUnderTest.useTheObject();
But for this I would need to modify the interface of my class, and I really don't want to do that. Is there anything else I can do?
You can use Typemock Isolator++ if you don't want to modify your interface or introduce extra indirection.
template <typename T>
class MyClass
{
public:
void someMethod()
{
T object;
object.doSomething();
}
};
class RealType //RealType is the actual production type, no injection needed
{
public:
void doSomething(){}
};
Since T is created inside someMethod (inside under test method), we need to fake the T's ctor.
FAKE_ALL does just that. The behavior set on fakeRealType will apply to all RealType instances created in runtime. The default FAKE_ALL behavior is a recursive fake, meaning that all the fakes's methods are faked and will return fake objects. You can also manually set any behavior you want on any method.
TEST_CLASS(MyTests)
{
public:
TEST_METHOD(Faking_Dependency_And_Asserting_It_Was_Called)
{
RealType* fakeRealType= FAKE_ALL<RealType>();
MyClass<RealType> myClassUnderTest;
myClassUnderTest.someMethod();
ASSERT_WAS_CALLED(fakeRealType->doSomething());
}
};
Typemock fakes are not strict, so you need to write an appropriate assert to make sure that your method was indeed called. You can do it using ASSERT_WAS_CALLED which is also provided by Typemock.
P.S I used MSTest.
You could redirect the doSomething member function to a static one e.g.
struct MockT
{
void doSomething() {
soSomethingS();
}
MOCK_STATIC_FUNCTION( doSomethingS, 0, void(), doSomething )
};
Then your test would be
BOOST_AUTO_TEST_CASE(testSomeMethod) {
MyClass<MockT> myClassUnderTest;
MOCK_EXPECT(MockT::doSomething).once();
myClassUnderTest.someMethod();
}
If needed you can test the construction and destruction of the object instance, but it likely doesn't bring much more to your test.
I found that the best is to use a shared pointer for the member. It is unfortunate that I have to use an extra indirection just because of the unit test, but at least it works well.
template <typename T, typename TFactory>
class MyClass {
...
void someMethod() {
std::shared_ptr<T> object = factory();
object->doSomething();
}
...
TFactory factory;
};
Then in the test it looks something like this:
BOOST_AUTO_TEST_CASE(testSomeMethod) {
std::shared_ptr<T> mockT;
MockTFactory factory(mockT);
MyClass<MockT, MockTFactory> myClassUnderTest(factory);
MOCK_EXPECT(mockT->doSomething).once();
myClassUnderTest.someMethod();
}
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.