How do I use google mock in C?
I found a way to be able to mock bare C functions in google-mock.
The solution is to declare foobar
to be a weak alias that maps to foobarImpl
. In production code you do not implement foobar()
and for unit tests you provide an implementation that calls a static mock object.
This solution is GCC specific but there are other compilers/linkers that provide weak aliasing.
- rename the function
void foobar();
tovoid foobarImpl();
- add an attribute to the function
foobar
like:void foobar() __attribute__((weak, alias("foobarImpl") ));
- if you want to have a non weak alias use a preproessor directive to remove the weak from the attributes.
Hence:
#pragma once
void foobar();
becomes
// header.h
#pragma once
void foobar();
void foobarImpl(); // real implementation
and
extern "C" {
#include "header.h"
}
// code.c
void foobarImpl() {
/* do sth */
}
void foobar() __attribute__(( weak, alias ("foobarImpl") )); // declare foobar to be a weak alias of foobarImpl
This will tell the gnu linker to link calls of foobar()
with foobarImpl()
whenever there is no symbol called foobar()
then add the testing code
struct FooInterface {
virtual ~FooInterface() {}
virtual void invokeFoo() const { }
};
class MockFoo : public FooInterface {
public:
MOCK_CONST_METHOD0(invokeFoo, void());
}
struct RealFoo : public FooInterface {
virtual ~RealFoo() {}
virtual void invokeFoo() const { foobarImpl(); }
};
MockFoo mockFoo;
RealFoo realFoo;
void foobar() {
mockFoo.invokeFoo();
}
if this code is compiled and linked it will replace foobar
with the mock call.
if you really want to call foobar()
you can still do add a default invocation.
ON_CALL(mockFoo, invokeFoo())
.WillByDefault(Invoke(&realFoo,&RealFoo::invokeFoo));
As from the Google Mock FAQ:
My code calls a static/global function. Can I mock it?
You can, but you need to make some changes.In general, if you find yourself needing to mock a static function, it's a sign that your modules are too tightly coupled (and less flexible, less reusable, less testable, etc). You are probably better off defining a small interface and call the function through that interface, which then can be easily mocked. It's a bit of work initially, but usually pays for itself quickly.
This Google Testing Blog post says it excellently. Check it out.
Your question specifically mentions Google Mock, but then does not state any other reason for using that framework. The other answer suggests using a workaround which seems unnecessarily intrusive.
Hence I hope I am allowed to make an alternative suggestion which works well without having to use weak aliases etc.
I have used CppUTest (https://cpputest.github.io/) for unit test with mock, successfully on a couple of large mainly-C projects (some C++). The mocking works without having to resort to any subterfuge of the above sort.
Unfortunately the project documentation is a little weak, some better (if a little agile-doctrinaire) information and examples in the book (also seen circulating as a PDF) "Test Driven Development for Embedded C" - James W Greening (ISBN-13: 978-1-934356-62-3)
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.