I having difficulty saving a pointer argument that my mock receives.
#define SIZE_OF_DATA
typedef struct {
uint32_t someValue1;
uint16_t someValue2;
// other values here
} LargeStruct;
class SomeClass {
public:
// assume sendData is a generic function where data is actually pointer to a LargeStruct
void sendData(const uint8_t* data, const uint16_t size);
}
class MockClass : public SomeClass {
public:
MOCK_METHOD2(sendData, void(const uint8_t*, const uint16_t));
};
I want to save the first argument to sendData (the pointer) and look at the data it points to (it points to a large struct, so I don't want to copy by value):
TEST(SomeFixture, sendData_checkSentDataIsValid) {
MockClass mock;
const uint8_t *pData;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA)).WillOnce(SaveArg<0>(&pData));
// do something here that calls sendData()
// hopefully data should point to the same data that was passed in to the method
LargeStruct *ls = (LargeStruct *)pData;
// now verify that the data is ok...
// some expectations here
EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1);
}
However, the data pointed to by pData is wrong - I think I appear to be saving the pointer value into the struct, rather than saving the pointer.
I think the problem lies in the variable I pass to SaveArg, but I can't seem to get it in a version that compiles and gives me the correct answer. Any pointers please?
So use ON_CALL by default, and only use EXPECT_CALL when you actually intend to verify that the call is made.
Using the Turtle interface as example, here are the simple steps you need to follow: Derive a class MockTurtle from Turtle . Take a virtual function of Turtle (while it's possible to mock non-virtual methods using templates, it's much more involved). In the public: section of the child class, write MOCK_METHOD();
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
In gMock we use the EXPECT_CALL() macro to set an expectation on a mock method. The general syntax is: EXPECT_CALL(mock_object, method(matchers)) . Times(cardinality) .
I just ran into the same situation, and in my case, I had to make sure that the pointer passed into the equivalent of your sendData() function was not pointing to an automatic variable on the stack. Otherwise, by the time you access the pointer, the contents will have changed. I found that less than helpful, so I decided to define a customized alternative to SaveArg like this:
ACTION_TEMPLATE(SaveSomeValue1,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer))
{
const void * data = ::std::tr1::get<k>(args);
const LargeStruct* ls = (const LargeStruct *)data;
*pointer = ls->someValue1;
}
You can then use it like this:
uint32_t someValue1;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
.WillOnce(SaveSomeValue1<0>(&someValue1));
//...
EXPECT_EQ(SOMEVALUEIWANT, someValue1);
You can create one void pointer as a buffer and save argument inside that buffer. After that you should cast the buffer to your large structure.
TEST(SomeFixture, sendData_checkSentDataIsValid) {
MockClass mock;
LargeStruct *ls;
void *buffer;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
.WillOnce(SaveArg<0>(&buffer));
// do something here that calls sendData()
ls = static_cast<LargeStruct *>(buffer);
EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1);
}
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