Giter Site home page Giter Site logo

javvalverde / c-mock Goto Github PK

View Code? Open in Web Editor NEW

This project forked from hjagodzinski/c-mock

0.0 2.0 0.0 26 KB

C Mock is Google Mock extension allowing for mocking functions.

License: BSD 2-Clause "Simplified" License

Makefile 1.66% Shell 2.10% C++ 87.40% C 8.83%

c-mock's Introduction

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.