Genmock allows to generate google mocks.
For example we need a mock for such an interface hello.h
:
#ifndef HELLO_H
#define HELLO_H
#include <hieverybody.h>
namespace abc {
namespace xyz {
class IHello
{
public:
virtual void sayHi() = 0;
};
} // xyz
} // abc
#endif // HELLO_H
We run the util (absolute output paths are required, because genmock creates intermediate directories):
genmock --mocktype=interface --outh=$(pwd)/test.h /path/to/hello.h
With the output:
#ifndef HELLO_MOCK_H
#define HELLO_MOCK_H
#include "hello.h"
#include <gmock/gmock.h>
namespace abc {
namespace xyz {
class HelloMock : public IHello
{
public:
MOCK_METHOD(void, sayHi, (), (override));
}; // class HelloMock
} // namespace xyz
} // namespace abc
#endif // HELLO_MOCK_H
There are more complex cases of C API, when we want to mock it via a singleton capi.h
:
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint32_t operation_a(const uint32_t* px);
void hi_again(const char* name, uint16_t times);
#ifdef __cplusplus
}
#endif
After:
bin/genmock --mocktype=singleton --outh=$(pwd)/CapiMock.h --outsrc=$(pwd)/CapiMock.cpp capi.h
Outputs are the following CapiMock.h
:
#ifndef CAPI_MOCK_H
#define CAPI_MOCK_H
#include "capi.h"
#include <estd/singleton.h>
#include <gmock/gmock.h>
class CapiMock : public ::esrlabs::estd::singleton<CapiMock>
{
public:
MOCK_METHOD(int, operation_a, (const int *));
MOCK_METHOD(void, hi_again, (const char *, int));
}; // class CapiMock
#endif // CAPI_MOCK_H
CapiMock.cpp
#include "capi.h"
#include "test.h"
extern "C" {
int operation_a(const int *px)
{
return CapiMock::instance().operation_a(px);
}
void hi_again(const char *name, int times)
{
CapiMock::instance().hi_again(name, times);
}
} // extern "C"
One case also requires a singleton to implement a mock:
#ifndef STATISTA_H
#define STATISTA_H
#include <hieverybody.h>
#include <stdint.h>
namespace abc {
namespace xyz {
class Statista
{
public:
static void calculate(uint32_t data);
static float median();
};
} // xyz
} // abc
#endif // STATISTA_H
We run genmock
bin/genmock --mocktype=singleton --outh=$(pwd)/StatistaMock.h --outsrc=$(pwd)/Statista.cpp Statista.h
With the following results StatistaMock.h
:
#ifndef STATISTA_MOCK_H
#define STATISTA_MOCK_H
#include "Statista.h"
#include <estd/singleton.h>
#include <gmock/gmock.h>
namespace abc {
namespace xyz {
class StatistaMock : public ::esrlabs::estd::singleton<StatistaMock>
{
public:
StatistaMock() : ::esrlabs::estd::singleton<StatistaMock>(*this) {}
MOCK_METHOD1(calculate, void(int));
MOCK_METHOD0(median, float());
}; // class StatistaMock
} // namespace xyz
} // namespace abc
#endif // STATISTA_MOCK_H
And StatistaMock.cpp
:
#include "Statista.h"
#include "test.h"
namespace abc {
namespace xyz {
void Statista::calculate(int data)
{
StatistaMock::instance().calculate(data);
}
float Statista::median()
{
return StatistaMock::instance().median();
}
} // namespace xyz
} // namespace abc
Genmock supports configuration. Either via --config argument or via the default path ~/.config/genmock/genmock.json
Configuration is a json file with 4 parameters:
{
"tab_length": 4,
"singleton_path": "<estd/singleton.h>",
"singleton_class": "::esrlabs::estd::singleton",
"style": "old"
}
The style parameter defines the style of google mock. See http://google.github.io/googletest/gmock_cook_book.html#old-style-mock_methodn-macros
Build requires cmake, ninja and nlohmann_json on the system level.
git clone --depth=1 https://github.com/llvm/llvm-project.git
cd llvm-project
git submodule add https://github.com/sky-mart/genmock.git clang-tools-extra/genmock
# add_subdirectory in clang-tools-extra/CMakeLists.txt
mkdir build
cd build
cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
ninja genmock -j16
cp bin/genmock ~/.local/bin/ # or other directory