I have developed Mockingbird a mocking framework for c++, it depends on function injection, here is the code from the repository:
/*
* Mockingbird is a simple and a powerful mocking framework for c++.
* Copyright (c) Mouaz Chamieh April 2021.
* Distributed under the MIT License. Please refer to the LICENSE file at:
* https://github.com/muazsh/Mockingbird
*/
#pragma once
#ifndef MOCKINGBIRD
#define MOCKINGBIRD
#define START_MOCK(MockingClass, MockedClass)\
class MockingClass : public MockedClass {\
public:
#define INJECTION_SET(FuncName, Substitute)\
private:\
template<class T>\
class FuncName##Class {\
public:\
FuncName##Class():m_func((T)Substitute){}\
T m_func;\
};\
FuncName##Class<decltype(Substitute)> m_##FuncName##Class;\
mutable int m_##FuncName##CallCounter = 0;\
public:\
void Inject##FuncName(decltype(Substitute) sub){\
m_##FuncName##Class.m_func = sub;}\
int Get##FuncName##CallCounter(){return m_##FuncName##CallCounter;}
#define FUNCTION(FuncName,ReturnType, Signature, Substitute, .../*signature variables*/)\
INJECTION_SET(FuncName, Substitute)\
ReturnType FuncName Signature override\
{ m_##FuncName##CallCounter++;\
return m_##FuncName##Class.m_func(__VA_ARGS__);}
#define CONST_FUNCTION(FuncName,ReturnType, Signature, Substitute, .../*signature variables*/)\
INJECTION_SET(FuncName, Substitute)\
ReturnType FuncName Signature const override\
{ m_##FuncName##CallCounter++;\
return m_##FuncName##Class.m_func(__VA_ARGS__);}
#define OVERLOAD_INJECTION_SET(FuncName, Substitute, overloadedMethodNumber)\
private:\
FuncName##Class<decltype(Substitute)> m_##FuncName##Class##overloadedMethodNumber;\
mutable int m_##FuncName##overloadedMethodNumber##CallCounter = 0;\
public:\
void Inject##FuncName(decltype(Substitute) sub){\
m_##FuncName##Class##overloadedMethodNumber.m_func = sub;}\
int Get##FuncName##overloadedMethodNumber##CallCounter(){return m_##FuncName##CallCounter;}
#define FUNCTION_OVERLOADING(FuncName,ReturnType, Signature, Substitute, overloadedMethodNumber, .../*signature variables*/)\
OVERLOAD_INJECTION_SET(FuncName, Substitute, overloadedMethodNumber)\
ReturnType FuncName Signature override\
{ m_##FuncName##overloadedMethodNumber##CallCounter++;\
return m_##FuncName##Class##overloadedMethodNumber.m_func(__VA_ARGS__);}
#define CONST_FUNCTION_OVERLOADING(FuncName,ReturnType, Signature, Substitute, overloadedMethodNumber, .../*signature variables*/)\
OVERLOAD_INJECTION_SET(FuncName, Substitute, overloadedMethodNumber)\
ReturnType FuncName Signature const override\
{ m_##FuncName##overloadedMethodNumber##CallCounter++;\
return m_##FuncName##Class##overloadedMethodNumber.m_func(__VA_ARGS__);}
#define END_MOCK(MockingClass)\
};
#endif // !MOCKINGBIRD
and here is an example on how it works:
Assume you have the following class Foo and you need to mock:
struct MyStruct{
int x, y;
};
class Foo{
public:
virtual const MyStruct CreateMyStruct(int x, int y) { return MyStruct{ x,y }; }
};
Then you write a testing fixture only once for the whole project:
const MyStruct CreateMyStructDummy(int x, int y) { return MyStruct{0,0}; }
START_MOCK(FooMock, Foo)
FUNCTION(CreateMyStruct, const MyStruct, (int x, int y), &CreateMyStructDummy, x, y)
END_MOCK(FooMock)
Then in the tests you write the desired substitute for example:
const MyStruct CreateMyStructSubstitute(int x, int y) { return MyStruct{ x + 10, y + 10 }; }
and inject it like:
FooMock fooMock;
fooMock.InjectCreateMyStruct(CreateMyStructSubstitute); // Mocking function injection.
auto created = fooMock.CreateMyStruct(5,5);
EXPECT_EQ(created.x, 15);
EXPECT_EQ(created.y, 15);
The code is in the file Mockingbird.hpp and totally depends on macros, it is short and straightforward, I ask for reviewing the code on github here, thanks.