-
Notifications
You must be signed in to change notification settings - Fork 1
Mocking
Often when testing a program you will find that there are external dependencies that you do not have access to. This can be a pain for testing as it becomes hard to tell if a test is failing due to these dependencies, so to get around this we mock those dependencies. A mock is just a simulation of another object.
- Go to the directory
hyped-2021/test/src/<ModuleYouWishToTest>
- Create the files
<NameOfTest>.test.cpp
and<NameOfTest>.test.hpp
- At the top of the header file you must include both the google test and google mock library
If I wished to create a test file for which required mocking the config in utils then each step would look like:
hyped-2021/test/src/utils
-
config.test.cpp
andconfig.test.hpp
- At the top of
config.test.hpp
I have#include "test/gtest.h"
and#include "mock/gmock.h"
In the header file you need to create a mock of the class/object you wish to mock. You can only mock the functions of a class/object that are virtual! If a function is not virtual then it means that it is an essential part of the system and you should not be mocking it.
Template for mocking:
class Mock<ClassName> : public <ClassName>
{
public:
MOCK_METHOD(<ReturnType>, <MethodName>, (<Args...>), (override));
};
In this file you can include test fixtures, individual unit tests and anything else that can be done as before but now you can also add mocks.
There are two main types of "assertions" for mocking
ON_CALL
This defines what happens when a mock method is called, but doesn't imply any expectation on the method being called.
EXPECT_CALL
This defines the behaviour but also sets an expectation that the method will be called with the given arguments, for the given number of times, and in the given order. This adds a lot of constraints to the call making you more prone to missing edge cases.
You can also specify how many times you wish for a method to be called as well as what it should return and other exciting possibilities which we encourage you to explore here: https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md
The possibilities for what you can do here are endless but the majority of the time you will be following the same template:
.test.hpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "<HeaderFileForClassToBeMocked>"
#include "<AnyLibrariesUsedInTesting>"
class Mock<MockedClass> : public <MockedClass>
{
public:
MOCK_METHOD(<ReturnType>, <MethodName>, (<Args...>), (override));
...
MOCK_METHOD(<ReturnType>, <MethodName>, (<Args...>), (override));
};
.test.cpp
#include "<ClassTest>.test.hpp"
TEST(<TestFixtureName>, <UniqueUnitTestName>)
{
// Establish any mocks you need to use here
Mock<MockedClass> <mockedClass>;
// Have any calls you want to test for here
EXPECT_CALL(<mockedClass>, <functionBeingCalled>(<Argument>)).<MANY_OPTIONAL_CONSTRAINTS>;
// Construct whatever objects you are using for the test
// (If not already made in a test fixture
<ObjectToBeTested> <objectToBeTested>(&<mockedClass>);
// Finally your assertions
EXPECT_TRUE(<objectToBeTested>.<functionBeingCalled>(<Argument>));
}
compWinner.test.hpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "HypedMachine.hpp"
#include "CompWinner.hpp"
class MockHypedMachine : public HypedMachine
{
public:
MOCK_METHOD(bool, year, int, (override));
};
compWinner.test.cpp
#include "compWinner.test.hpp"
TEST(nextComp, CallsHypedMachineYear)
{
MockHypedMachine hypedMachine;
EXPECT_CALL(hypedMachine, year(2021));
CompWinner compWinner(&hypedMachine);
EXPECT_TRUE(compWinner.nextComp());
}
So in the above example we are assuming there is a class called HypedMachine
with a function called year()
which takes in a year and returns true
if the HypedMachine will win the competition that year. We however wish to test another class called CompWinner
which has a function nextComp()
- this returns true if there is a winner for the next competition. nextComp()
we are assuming goes through all the teams and will return true if at least one teams year()
function returns true. Hence we are testing that the function year()
in the HypedMachine
is in fact called.
Optional constraints can be powerful when used in small quantities but the more you add the more you are overfitting to certain circumstances.
The constraints can be added to the EXPECT_CALL
or the ON_CALL
. E.g EXPECT_CALL(<mockedClass>, <functionBeingCalled>(<Argument>)).<OPTIONAL_CONSTRAINTS>
WillOnce(testing::Return(<value>));
This ensures that the first time <functionBeingCalled>
is called it will return <value>
.
E.g. EXPECT_CALL(hypedMachine, year(2020)).WillOnce(testing::Return(true));
.
- Home
- How to add and edit pages on the wiki
- Glossary
- Admin
- Projects & Subsystems
- Motor Controllers
- Navigation
- Quality Assurance
- Sensors
- State Machine
- Telemetry
- Technical Guides
- BeagleBone Black (BBB)
- Configuration
- Contributing
- Testing
- Install VM on Mac
- Makefiles
- Reinstall MacOS Mojave
- Travis Troubleshooting
- Knowledge Base