In this example we are going to show you how to mock and test a private function using BonoboMock.
Note: In optimized builds (e.g., CMake build types
RelWithDebInfoorRelease), the compiler may inline functions, preventing BonoboMock from intercepting calls. See Function inlining for this limitation and the available mitigations using the optimization macros and CMake helper.
Note: If your project uses C++03,
autois unavailable. Explicitly declare the mock type instead — see Explicit Mock Object Types.
Note: Private function mocking does not support function overloading (functions with the same name) because BonoboMock uses string-based symbol table lookup to resolve private function addresses. See Limitations for details.
Note: In order to mock private methods, the
BONOBO_MOCK_PRIVATE_*macros scan the symbol table of the test binary on first use. This can have significant runtime cost for a large test binary. We recommend usingadd_testrather thangtest_discover_testsorcatch_discover_testsfor optimal performance.
BonoboMock can mock private static member functions using the BONOBO_MOCK_PRIVATE_STATIC family of macros. Because static functions have free-function signatures (no implicit this pointer), they use a simpler workflow than private non-static members — no class parameter or const/non-const distinction is needed.
class SampleClassPrivate {
public:
static int call_private_static(int* in) {
return private_static_function(in);
}
private:
static int private_static_function(int* in) {
return *in;
}
};
BonoboMock needs to know the function signature of the private static function, but it cannot access private members directly. Define a free function with the same signature — its body does not matter, as it is never called:
int function_with_same_signature_as_private_static_function(int* in) {
return *in; // never called — only used for type deduction
}
TEST(PrivateStatic, Mock_private_static) {
#ifdef BSLS_COMPILERFEATURES_FULL_CPP11
auto mock = BONOBO_MOCK_PRIVATE_STATIC(
Namespace::SampleClassPrivate::private_static_function,
&function_with_same_signature_as_private_static_function);
#else
bsl::shared_ptr<GMock<int(int*)> > mock = BONOBO_MOCK_PRIVATE_STATIC(
Namespace::SampleClassPrivate::private_static_function,
&function_with_same_signature_as_private_static_function);
#endif
EXPECT_CALL(*mock, BONOBO_MOCK_FUNCTION(_))
.Times(1)
.WillOnce(Return(100));
int input = 10;
EXPECT_EQ(100, SampleClassPrivate::call_private_static(&input));
mock->restore();
EXPECT_EQ(10, SampleClassPrivate::call_private_static(&input));
}
Use BONOBO_MOCK_PRIVATE_STATIC to create the mock — the first argument is the fully qualified function name, the second is the address of the signature-conveying free function. The address is resolved via symbol table lookup on first use.
Unlike private non-static member functions, there is no class parameter and no this pointer in the matchers — BONOBO_MOCK_FUNCTION receives only the actual function arguments.
Strict and nice variants are also available: BONOBO_MOCK_PRIVATE_STATIC_STRICT and BONOBO_MOCK_PRIVATE_STATIC_NICE. See Naggy, Nice, and Strict Mocks for details.
BonoboMock can mock private non-static member functions regardless of whether they are const or non-const, virtual or non-virtual. The following sample code only shows the mocking of a non-const, non-virtual, private function. More examples can be found among the unit test files for the library under tests/unit/.
Let’s define a class SampleClassPrivate that has a private function – private_member_function. It also contains a public function which serves as a wrapper of the private one:
class SampleClassPrivate {
public:
int call_private(int* in) {
return private_member_function(in);
}
private:
int private_member_function(int* in) {
return *in;
}
};
BonoboMock needs to know the function signature of the private function, but it cannot access private members directly. We define a free function with the same signature — its body does not matter, as it is never called. It exists only to convey the type to BonoboMock:
int function_with_same_signature_as_private_member_function(int* in) {
return *in; // never called — only used for type deduction
}
To demonstrate that BonoboMock can intercept calls to the private function on objects the test does not control, we define a free function that creates its own SampleClassPrivate and calls the private function through its public wrapper:
int call_private_via_local_object(int* in) {
SampleClassPrivate obj;
return obj.call_private(in);
}
TEST(Private, Mock_non_const_private) {
#ifdef BSLS_COMPILERFEATURES_FULL_CPP11
auto mock = BONOBO_MOCK_PRIVATE_NON_CONST(
BloombergLP::bonobomock::test::SampleClassPrivate::private_member_function,
BloombergLP::bonobomock::test::SampleClassPrivate,
&function_with_same_signature_as_private_member_function);
#else
bsl::shared_ptr<GMock<int(void*, int*)> > mock =
BONOBO_MOCK_PRIVATE_NON_CONST(
BloombergLP::bonobomock::test::SampleClassPrivate::private_member_function,
BloombergLP::bonobomock::test::SampleClassPrivate,
&function_with_same_signature_as_private_member_function);
#endif
SampleClassPrivate obj;
EXPECT_CALL(*mock, BONOBO_MOCK_FUNCTION(_, _))
.Times(1)
.WillOnce(Return(100));
EXPECT_CALL(*mock, BONOBO_MOCK_FUNCTION(&obj, _))
.Times(1)
.WillOnce(Return(200));
int input = 10;
EXPECT_EQ(200, obj.call_private(&input));
EXPECT_EQ(100, call_private_via_local_object(&input));
mock->restore();
EXPECT_EQ(10, obj.call_private(&input));
EXPECT_EQ(10, call_private_via_local_object(&input));
}
To mock a private function, use BONOBO_MOCK_PRIVATE_NON_CONST to create the mock object. The first argument is the full name of the function, the second is the full name of the class, and the third is the address of the signature-conveying free function. The function address is resolved via symbol table lookup on first use.
The rest of the code is quite similar to Non-virtual Member Function Mocking.
You can find additional examples among the unit test files for the library under tests/unit/.