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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With