I realize this is a super old thread, but I'm hoping I can make someone's life a little easier if and when they come across this question.
You can very easily autogenerate mocks for C functions that are compatible with GoogleTest using Mimicc. Find whatever header files declare the functions you want to mock, "compile" them into mock implementation object files, and link them into your test binary including definitions of the mock_fatal()
and mock_failure()
functions as described in the User Guide specifically for Google Test. You'll have to use the Mimicc API for interacting with the Mimicc-generated mocks (i.e. it doesn't use GoogleMock's API for setting expectations, etc.), but they can comfortably live alongside the GoogleMock-generated mocks.
To be more concrete, suppose you have a C header file foo.h
which declares a few functions you want to mock. For example:
/*!
* @param[out] pBuf Destination buffer to read to
* @param[in] sz Size of the read buffer
*/
int magic_read(char *pBuf, const size_t sz);
/*!
* @param[in] pBuf Source buffer to write from
* @param[in] sz Size of the write buffer
*/
int magic_write(const char *pBuf, const size_t sz);
You can create mocks for these by compiling foo.h
with all the same CFLAGS
that would be used to compile the accompanying production foo.c
:
prompt$ mimicc -c foo.h -o mock.o --hout=foo-mock.h -DSOME_PREPROC=1 -I <your includes>
To use this in a test, set expectations and returns using the API declared in foo-mock.h
as shown on the command line invocation above. Include the implementation of mock_fatal()
and mock_failure()
for Google Test.
#include <gtest/gtest.h>
#include <memory>
std::unique_ptr<char []> mockErrStr(const char *pLocation, unsigned count, const char *pMsg)
{
const char *pFmtStr = "mock assertion failure! location: '%s',"
" iteration: %d, message: %s";
size_t n = snprintf(NULL, 0, pFmtStr, pLocation, count, pMsg);
std::unique_ptr<char []> outStrBuf(new char[n+1]);
snprintf(outStrBuf.get(), n+1, pFmtStr, pLocation, count, pMsg);
return outStrBuf;
}
void mock_failure(const char *pLocation, unsigned count, const char *pMsg)
{
ADD_FAILURE() << mockErrStr(pLocation, count, pMsg).get();
}
void mock_fatal(const char *pLocation, unsigned count, const char *pMsg)
{
FAIL() << mockErrStr(pLocation, count, pMsg).get();
exit(1);
}
TEST_F(MimiccPoC, test1)
{
char mock_ret_data[] = "HELLO WORLD";
MOCK_FUNCTIONS(foo).magic_read.expect(32);
MOCK_FUNCTIONS(foo).magic_read.andReturn(
1, mock_ret_data, sizeof(mock_ret_data));
char testRetBuf[32];
int testRes = magic_read(testRetBuf, sizeof(testRetBuf));
ASSERT_EQ(1, testRes);
ASSERT_STREQ(testRetBuf, "HELLO WORLD");
}
While this may seem like a lot, once the plumbing is set up, you can automatically mock any C or C++ code you have without actually having to write or maintain additional mock code, you just focus on the tests. Quite a bit easier in the long run.