Skip to content

sharpglasses/C-Mock

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C Mock - Google Mock Extension

Overview

C Mock is Google Mock extension allowing for mocking functions.

This is not either a patch to nor fork of Google Mock. This is just a set of headers providing a way of using tools for mock methods with mock functions in tests.

C Mock is not intended to promote bad design. Its goal is to help people test their code.

Before use of C Mock following reading is recommended:

Requirements

  • Google Mock (1.6 or newer)
  • GNU/Linux platform that Google Mock supports

Guide

C Mock requires no prior build. As already mentioned it is just a set of header files. What it really gives you are four macros:

  • DECLARE_FUNCTION_MOCK*
  • IMPLEMENT_FUNCTION_MOCK*
  • EXPECT_FUNCTION_CALL
  • ON_FUNCTION_CALL

These macros do what theirs' method counterparts do MOCK_METHOD_*, EXPECT_CALL and ON_CALL, respectively. There are small differences though.

Creating mock

Both DECLARE_FUNCTION_MOCK* and IMPLEMENT_FUNCTION_MOCK* in fact stand for a series of macros for defining and implementing C function mocks, respectively. These macros take three arguments: mock class name, function name and function prototype.

C Mock internally redefines function being mocked. Because only one implementation of a function might exist in executable, splitting of declaration and implementation is necessary. Especially, if mocking of a certain function is happening in a more than one compilation unit. Therefore declaration should be put in a header file whereas implementation in a source file.

C Mock does not know whether mocked function is declared with name mangling - whether this is a pure C function or a C++ function. Therefore C Mock does not redeclare mocked function. Original function prototype declaration should be used (i.e. use of original function header file).

Suppose you want to mock int foo(int, int) function declared in foo.h header file and name mock class FooFunctionMock. You could create two files, one header with declaration and one source file with implementation:

  • foo_mock.h

          #include "foo.h" // use original function declaration
    
          DECLARE_FUNCTION_MOCK2(FooFunctionMock, foo, int(int, int));
    
  • foo_mock.cc

          IMPLEMENT_FUNCTION_MOCK2(FooFunctionMock, foo, int(int, int));
    

Specifying expectations

EXPECT_FUNCTION_CALL and ON_FUNCTION_CALL do exactly what theirs' method equivalents. Both take two arguments: mock class instance and arguments you expect - there is no need to repeat function name since it is already known at this point. Suppose we expect foo function to be called once with arguments 1 and 2, and want it to return 3:

    FooFunctionMock mock;
    EXPECT_FUNCTION_CALL(mock, (1, 2)).WillOnce(::testing::Return(3));

Function is mocked as long as its corresponding mock class instance exists. This means function is mocked only when required.

    {
        {
            FooFunctionMock mock;
            /* ... */
            foo(1, 2); // call mock
        }

        foo(1, 2); // call real function
    }

Event though you mock function, you might want to use its real implementation. Each mock class exports static real class field which holds pointer to real function.

    FooFunctionMock mock;
    EXPECT_FUNCTION_CALL(mock, (1, 2)).WillOnce(::testing::Invoke(FooFunctionMock::real));
    foo(1, 2); // call real function

Building

C Mock uses internally some tricks specific to GNU/Linux platform and a test building requires a few additional steps.

Firstly, all functions you want to mock must be in dynamic libraries. If it includes your project-specific functions you must put them to dynamic library. In such a circumstances it seems reasonable to build all code under test as a dynamic library. Selecting only those parts that you are going to mock might be tedious and cumbersome.

Secondly, you must pass following options to linker when building test executable:

  • -rdynamic - add all symbols to dynamic symbol table
  • -Wl,--no-as-needed - link with library event though during static linking there are no dependencies to it
  • -ldl - dynamic linking loader library

C Mock comes with cmock-config tool to hide all these details away from you. Run

    cmock-config --cflags

and

    cmock-config --libs [path to libgmock [path to libgtest]]

to get compilations and linker options, respectively.

Note: Since it is [not recommended to install a pre-compiled version of Google Test][4] (or Google Mock) many distributions don't provide such libs anymore. You need to download and compile those libs as described in the README of the Google Mock sources. For the linker to find libgmock and libgtest you can pass the paths to those libs to the cmock-config script. If you omit the path to libgtest it defaults to "pathToLibgmock/libgtest".

Let's say you built a code under test into libfoo.so and put a test code in bar.cc. To build your test executable you would run:

    g++ `cmock-config --cflags` -c bar.cc -o bar.o
    g++ `cmock-config --libs` -pthread -lfoo bar.o -o bar # Google Test requires -pthread

When building code under test as a dynamic library it is handy to specify soname as an absolute path name. Then when test executable is run no additional environment setup is required for dynamic linking loader to locate your library (i.e. setting LD_LIBRARY_PATH).

Installation

To install run:

    make install

To uninstall run:

    make uninstall

By default instalation PREFIX is /usr/local. Change it in command line if required.

Test

If your platform is supported, the following commands should succeed:

    make
    make test

Tests are quite simple and are good source of example.

References

[3]: http://googletesting.blogspot.com/2008/06/defeat-static-cling.html "Defeat "Static Cling"" [4]: https://code.google.com/p/googletest/wiki/FAQ#Why_is_it_not_recommended_to_install_a_pre-compiled_copy_of_Goog

About

C Mock is Google Mock extension allowing for mocking functions.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 91.8%
  • C 4.4%
  • Shell 2.1%
  • Makefile 1.7%