Can gmock be used for stubbing C functions?

Shan Rehman picture Shan Rehman · Aug 13, 2015 · Viewed 21.5k times · Source

I am new to gmock, so I want to know how can I stub simple C function called in a function under test for Unit Testing.

Example:

int func(int a)
{
  boolean find;
  // Some code
  find = func_1();
  return find;
}

I have searched about gmock and in my understanding gmock does not provide functionality to stub simple C functions, therefore I want to ask does gmock provides functionality to mock or stub func_1?

If not how can I stub func_1 manually in my test code without changing source code? I am using google test framework for unit testing.

Thanks.

Answer

Georg P. picture Georg P. · Aug 28, 2015

I found myself in the same situation lately. I had to write unit tests for libraries written in C, which in turn had dependencies to other libraries also written in C. So I wanted to mock all function calls of dependencies using gmock. Let me explain my approach by an example.

Assume the code to be tested (library A) calls a function from another library, lib_x_function():

lib_a_function()
{
   ...
   retval = lib_x_function();
   ...
}

So, I want to mock the library X. Therefore I write an interface class and a mock class in a file lib_x_mock.h:

class LibXInterface {
public:
   virtual ~LibXInterface() {}
   virtual int lib_x_function() = 0;
}

class LibXMock : public LibXInterface {
public:
   virtual ~LibXMock() {}
   MOCK_METHOD0(lib_x_function, int());
}

Additionally I create a source file (say, lib_x_mock.cc), that defines a stub for the actual C function. This shall call the mock method. Note the extern reference to the mock object.

#include lib_x.h
#include lib_x_mock.h
extern LibXMock LibXMockObj;    /* This is just a declaration! The actual
                                   mock obj must be defined globally in your
                                   test file. */

int lib_x_function()
{
    return LibXMockObj.lib_x_function();
}

Now, in the test file, which tests the library A, I must define the mock object globally, so that it is both reachable within your tests and from lib_x_mock.cc. This is lib_a_tests.cc:

#include lib_x_mock.h

LibXMock LibXMockObj;  /* This is now the actual definition of the mock obj */

...
TEST_F(foo, bar)
{
   EXPECT_CALL(LibXMockObj, lib_x_function());
   ...
}

This approach works perfectly for me, and I have dozens of tests and several mocked libraries. However, I have a few doubts if it is ok to create a global mock object - I asked this in a separate question and still wait for answers. Besides this I'm happy with the solution.


EDIT: The problem about the global object can be easily remedied by creating the object e.g. in the constructor of the test fixture, and just storing a pointer to that object in a global variable.

However, also note my alternative answer to this question, that I just posted.