Reputation: 193
So I am trying to learn how to write unit Tests and i stumbled upon the problem, that I don't understand how to create mock objects. Here's my example: I have this class:
class FooChild
{
public:
void doThis();
bool doThat(int n, double x);
};
And this is a method in another class I want to test:
#include "FooFighter.h"
#include "FooChild.h"
void FooFighter::doSomething()
{
FooChild fooChild;
fooChild.doThis();
fooChild.doThat(4, 5);
}
I want to test Things like if it called the method and how many times. The Google mock documentary says, that only Abstract classes with virtual methods can be mocked. That's why i tried to create a parent class of FooChild, like this:
class Foo
{
public:
virtual void doThis() = 0;
virtual bool doThat(int n, double x) = 0;
};
And then create a mock class of Foo like this:
#include "gmock/gmock.h"
class MockFoo : public Foo
{
public:
MOCK_METHOD(void, doThis, (), (override));
MOCK_METHOD(bool, doThat, (int n, double x), (override));
};
Then I tried to write the Test for doSomething:
TEST_F(FooFighterTest, doSomethingTest)
{
MockFoo mock_foo
mock_foo.doThis()
.Times(1);
}
Clearly this doesn't work and I have the feeling that I completely misunderstood how mocks work, but I just can't seem to find a nice and simple explanation on how to create mocks. Any help or advice would be great. Also my approach on how to test void functions like this might be completely wrong, so any advice on how to test functions that don't return anything would be great too.
Upvotes: 7
Views: 15151
Reputation: 3521
Your example is not too far off from working. You would probably find it helpful to read the gMock for Dummies document. It gives a good overview of the basics.
Essentially mocks allow you to set expectations on them, and verify that the expectations were met. You can also do things like control return values of mocked methods. Mocked methods must be virtual, but there is no requirement that they be abstract.
class FooChild
{
public:
virtual void doThis() {}
virtual bool doThat(int n, double x) { return false; }
};
class MockFooChild : public FooChild
{
public:
MOCK_METHOD(void, doThis, (), (override));
MOCK_METHOD(bool, doThat, (int n, double x), (override));
};
The biggest problem with in your example is that FooFighter::doSomething
is using the concrete (real) class FooChild
. You will need a way to substitute the the concrete class with the mocked class (using some form of dependency injection). Here's a simple example:
class FooFighter
{
public:
void doSomething(FooChild &fooChild)
{
fooChild.doThis();
fooChild.doThat(4, 5);
}
};
Now you can test that FooFighter::doSomething
is doing what it is expected to:
TEST(FooFighterTest, doSomethingTest)
{
MockFooChild mockFooChild;
FooFighter fooFighter;
// doThis() must be called exactly 1 time.
EXPECT_CALL(mockFooChild, doThis).Times(Exactly(1));
// doThat() must be called exactly 1 time with parameters 4,5
EXPECT_CALL(mockFooChild, doThat(4,5)).Times(Exactly(1));
fooFighter.doSomething(mockFooChild);
}
Upvotes: 6
Reputation: 95
You are missing quite a few things unless you are not putting them here. Read slowly the documentation of the googletests and specifically the mocks. This is how I usually define the mocks:
#include <gmock/gmock.h>
#include "Foo.hpp"
class MockFoo : public Foo {
public:
MOCK_METHOD0(doThis, void());
MOCK_METHOD2(doThat, bool(int n, double x));
};
You need to write the number of arguments of the methods after the expression MOCK_METHOD
, then the return type and between parenthesis the types of the arguments. If you don't want to worry about this use this nice generator that is in the library.
Then in the tests itself is where you define the behavior of the mock, that is the point of it, you can do a general definition for all the tests or change it in some to work differently.
I think it doesn't make sense to write a full example because you have in the tutorials really good and simple ones, so check it.
Upvotes: 0