EasyMock
The easy mocking framework for writing unit tests
Install / Use
/learn @lcarlier/EasyMockREADME
Welcome to EasyMock
<a name="user-content-wie"></a> What is EasyMock ?
EasyMock is a tool which generates mocks of C functions by parsing a header file. The mocks can be configured to return a specific value on a specific call. When the mocked function is called, the input argument can be compared to a specific value to verify that the code calling them gives the correct parameters to the mock.
Mocks are very useful when writing unit tests. Thanks to the mocks, the build of the unit tests remains very small because it cuts the dependencies as soon as possible. Also, mocks can be used to validate that a specific functions calls the dependencies with the correct parameters. Then, mocks can be used to check that the function you are testing processes correctly the data returned by the dependencies.
EasyMock is very flexible to reproduce production scenarios because of its flexibility of configuring the mocks.
EasyMock can be used to mock Linux kernel header files to write unit test for validating a Linux kernel driver. An example on how to do so is available in the simple FIFO kernel module project.
Table of content
- [What is EasyMock ?][whatIsEasymock]
- [How to compile EasyMock ?][compileEasymock]
- [Release vs Debug build][relVsDeb]
- [Dependencies][dependencies]
- [Linux][linux]
- [MacOS][macos]
- [Compilation steps][compilationSteps]
- [libEasyMockFramework's API][libEasyAPI]
- [Create a mock][createAMock]
- [Generated mocks][genFun]
- [C functions][genFunC]
- [C++ functions][genFunCpp]
- [Free functions][genFunCppFf]
- [Class member functions][genFunCppCmf]
- [Comparators][genFunCppCmp]
- [Using the mocks][usingMock]
- [C functions and C++ free functions][usingMockCff]
- [C++ member functions][usingMockCppmf]
- [Unit tested][ut]
- [I want to participate in the development of EasyMock][participate]
- [Restriction][restriction]
- [Bug report][bugReport]
- [License of the tool][loft]
- [License of the generated code][logc]
- [The final note][finalNote]
- [Thanks][thanks]
<a name="user-content-htce"></a> How to compile EasyMock ?
EasyMock can be compiled on Linux or macOS x86_64/arm.
<a name="user-content-dependencies"></a> Dependencies
EasyMock uses the following mandatory libraries:
- libclang
- libclang-cpp
- libllvm
- libctemplate
- libncurse
- liboost (system, filesystem)
Additionally, the following optional libraries can be installed to enable printing the backtrace in the error messages:
- libunwind
- libdw
The following mandatory tools must be installed:
- A C/C++ compiler:
- gcc/g++
- clang/clang++ (Minimum version 8.0)
- cmake
- pkg-config
For generating the documentation, the following tools must be installed:
- doxygen
- graphviz
<a name="user-content-linux"></a> Linux
The dependencies can be installed on Ubuntu by using the following command:
sudo apt install \
g++ \
clang \
cmake \
pkg-config \
libunwind-dev \
llvm-dev \
libclang-dev \
libclang-cpp-dev \
libncurses-dev \
libboost-system-dev \
libboost-filesystem-dev \
libctemplate-dev \
libdw-dev \
doxygen \
graphviz
<a name="user-content-macos"></a> MacOS
libunwind and libdw are not available in macOS, as such the backtrace support is not supported on macOS.
The dependencies can be installed can be installed via brew.
brew install cmake \
pkgconfig \
ncurses \
gcc \
llvm \
ctemplate \
doxygen \
boost
<a name="user-content-compilation-steps"></a> Compilation steps
EasyMock uses CMake as software build management. The commands below can be used to compile the tool. Before copying and pasting those lines in your terminal, make sure first to set the EASYMOCK_SOURCE environment variable to the place where the EasyMock's code is installed.
cd $EASYMOCK_SOURCE
mkdir build #Referred as $EASYMOCK_BUILDDIR below
cd build
cmake ..
make -j $(nproc)
Note: On macOS, the following command cmake ../ -GXcode <rest of parameters> can be used to generate the
Xcode project to be opened with Xcode IDE, but the Makefiles
work just fine.
When the compilation is finished
- on Linux:
- the binary to generate the mock called [EasyMockGenerate][createAMock] is
under
$EASYMOCK_BUILDDIR/src/easyMockGenerate/src/EasyMockGenerate - the shared library to be linked to the unit test called
[libEasyMockFramework.so][libEasyAPI]
is under
$EASYMOCK_BUILDDIR/src/easyMockFramework/src/libEasyMockFramework.so
- the binary to generate the mock called [EasyMockGenerate][createAMock] is
under
- on macOS:
- the binary to generate the mock called [EasyMockGenerate][createAMock] is
under
$EASYMOCK_BUILDDIR/src/easyMockGenerate/src/<buildType>/EasyMockGenerate - the shared library to be linked to the unit test called
[libEasyMockFramework.dylib][libEasyAPI]
is under
$EASYMOCK_BUILDDIR/src/easyMockFramework/src/<buildType>/libEasyMockFramework.dylib
- the binary to generate the mock called [EasyMockGenerate][createAMock] is
under
<a name="user-content-rvdb"></a> Release vs Debug build
If you download the compressed archive of EasyMock, the release build is compiled. The release build produces:
- [EasyMockGenerate][createAMock] which is the binary which can be used to generate mocks.
libEasyMockFramework.sowhich is a shared library to be linked to the final unit test binary. See the [hello world example][helloWorldExample] for a full example on how to use it.
The debug build is selected when one of the following condition is met
- the directory
$EASYMOCK_SOURCE/.gitis present (it can be empty). - the directory
$EASYMOCK_SOURCE/.hgis present (it can be empty). - the following parameter is given to the cmake command:
-DCMAKE_BUILD_TYPE=Debug
The debug build passes extra debug compilation flags and takes longer because it
also compiles all the [tests][ut]. After the debug build has been
built, use the command make check to run all the tests.
<a name="user-content-libeasyapi"></a> libEasyMockFramework's API
The unit test which is using libEasyMockFramework.so should include
easyMock.h which is in $EASYMOCK_SOURCE/src/easyMockFramework/include/.
A good practice to allow your code to be able to include that header
is to use the -I option to point to that directory.
That file defines a set of C api to initialise the EasyMock framework and check that the mocks have been called as expected.
Even though EasyMock is implemented in C++, it was chosen to provide a C API to not force the unit test to be written in C++.
For the ease of accessibility, the documentation has been copied into this page.
See the [hello world example][helloWorldExample] for a full example on how to use them.
/*
* Initialises EasyMock.
*
* This must be called at the beginning of every test case.
*/
void easyMock_init();
/*
* Checks that EasyMock has reported at least one error.
*
* This must be called at the end of a unit test after the function being tested
* has been called. If an error has happened, the API easyMock_getError* can be
* used to retrieve the error messages.
*
* Returns 1 if no error has happened.
* Returns 0 if at least an error has happened.
*/
int easyMock_check();
/*
* Returns all the errors in a single buffer.
*
* The buffer can directly be printed to the standard output if needed.
*
* The returned buffer must not be freed by the caller.
*/
const char *easyMock_getErrorStr();
/*
* Returns all the errors in an array of pointer to constant array of characters.
*
* The parameter size is an output value which tells how many errors
* are reported into the array.
*
* The returned buffer must not be freed by the caller.
*/
const char ** easyMock_getErrorArr(unsigned int *size);
/*
* Sets whether the error messages should contain the call stack or not.
*
* The default is to print the callstack into the error messages.
*/
void easyMock_printCallStack(bool val);
/*
* Sets whether the mock should verify if the mocks have been called in the
* order they have been expected.
*
* The default is to check that the mocks have been called in the order they
* have been expected (via the *_ExpectAndReturn* API)
*/
void easyMock_checkCallsOrder(bool val);
<a name="user-content-cam"></a>Create a mock
A good start to get acquainted with EasyMockGenerate is to look at its help.
# ./EasyMockGenerate -h
Generate mocks to be used into unit tests.
EasyMock takes a header file ('-i') and generate a mocked version of functions declared in that header file in a target directory ('-o').
The tool generates mocks for functions directly declared in the header file. I.e. not coming from other included files.
'--generate-included-functions' option can be used to generate mocks of functions declared in included files.
Parameters not recognised by EasyMock (e.g. -I, -D) are given to the parser responsible for parsing the header file.
The same options used by a Clang compiler are recognised by EasyMock's parser.
Usage:
./EasyMockGenerate [OPTIONS...]
OPTIONS are:
-i <header> Input header file.
-o <directory> Output directory.
--mock-cpp Mock C++ header.
--cwd <directory> Change to the directory passed on this parameter before running the parser.
Relative paths given to '-i' and '-o' will be taken from the path given to '--cwd'.
--mock-only <function> Mock only the function specified in this parameter.
--generate-types Generate the used type instead of including the original header.
When using this option, the original header (i.e. the header given to -i) doesn't
need to be used when compiling the mock.
The generated functions signature will not contain any function attribute unless
the --generate-attribute opti
