I'm maintaining a legacy project written in C and it's unfeasible to get it running with a C++ compiler. Since the code is cross compiled it is however possible to run unit-tests or similar in a host environment. hence it's also possible to interface with a C++ host compiler and use google-test and google-mock.
There are certain capabilities of google-mock which seem to be very tempting to be used for testing as invoking real implementations and setting call expectations.
I would like to be able to use them in C code. I can see that it is indeed possible to use google-mock without using vtables, but it requires templates.
Is there a way to mock bare C functions with google mock?
EDIT:
I basically had to use google mock, I assume though that everybody else who will read this thread has better flexibility than me.
Google test, or gtest is an open source framework for unit testing C\C++ projects. It easily integrates with CMake, has a great assertion engine, and produces XML reports to be for display so that it can be integrated with common CI\CD frameworks.
A mock is a simulated function or module that mimics the behavior of a real implementation but is fully controlled by the unit test itself. The programmer can validate how many times a mock is called and verify the value of all arguments passed into the mock.
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.
void foobar();
to void foobarImpl();
foobar
like: void foobar() __attribute__((weak, alias("foobarImpl") ));
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.
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