I have a class Foo
that stores a pointer to a callback. The callback could be invoked with a method InvokeCallback()
.
void* SomeCallback(void* a) {
return (void*)(*(int*)a + 10);
}
class Foo {
public:
typedef void* (*CallbackFunction)(void*);
SetCallback(CallbackFunction callback) {
this->callback = callback;
}
InvokeCallback() {
callback(20);
}
private:
CallbackFunction callback;
}
How is it possible to test (using google test) that SomeCallback()
was invoked with a specific parameter (20 in the abovementioned case)?
EDIT:
I came up with a very ugly looking solution. The tests are passed, but the new error appeared at the end ERROR: 1 leaked mock object found at program exit
.
class MockCallbackClass {
public:
MOCK_METHOD1(SomeCallback, void*(void*));
};
MockCallbackClass mock; // Nasty global variable
void* __SomeOtherCallback(void* a) {
return mock.SomeCallback(a);
}
TEST(Callback, MockCallback) {
Foo foo;
foo.SetCallback(__SomeOtherCallback);
EXPECT_CALL(mock, SomeCallback((void*)10)).WillOnce(testing::Return((void*)20));
}
Google C++ Mocking Framework (or Google Mock for short) is a library (sometimes we also call it a “framework” to make it sound cool) for creating mock classes and using them. It does to C++ what jMock and EasyMock do to Java.
EXPECT_CALL not only defines the behavior, 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 when you specify the order too).
Gmock is a mocking framework for the Groovy language. Gmock is all about simple syntax and readability of your tests so you spend less time learning the framework and more writing code. To use Gmock just drop the gmock jar file in your classpath.
A matcher matches a single argument. You can use it inside ON_CALL() or EXPECT_CALL() , or use it to validate a value directly using two macros: Macro.
Use std::function<void*(void*)>
and testing::MockFunction<void*(void*)>
to mock this std::function
. Of course this requires slight changes in your implementation - but functionality of your design does not change, because raw function pointers can be stored in std::function
without problems:
class Foo {
public:
using CallbackFunction = std::function<void*(void*)>;
// rest of this class is as it was
};
And test like this:
class FooTest : public testing::Test {
public:
using CallbackFunctionMock = testing::MockFunction<void*(void*)>;
CallbackFunctionMock callbackFunctionMock;
Foo objectUnderTest{[this](void* v) { return callbackFunctionMock.Call(v); }};
};
TEST_F(FooTest, shallCallbackBeCalledByInvoke)
{
int a = 40;
EXPECT_CALL(callbackFunctionMock, Call(reinterpret_cast<void*>(20)).WillOnce(Return((void*)(&a));
objectUnderTest.InvokeCallback();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With