fake/mock nonvirtual C++ methods

后端 未结 8 1677
谎友^
谎友^ 2020-12-13 19:32

It known that in C++ mocking/faking nonvirtual methods for testing is hard. For example, cookbook of googlemock has two suggestion - both mean to modify original source code

8条回答
  •  不知归路
    2020-12-13 20:26

    I followed the Link Seam link from sdg's answer. There I read about different types of seams, but I was most impressed by Preprocessing Seams. This made me think about exploiting further the preprocessor. It turned out that it is possible to mock any external dependency without actually changing the calling code.

    To do this, you have to compile the calling source file with a substitute dependency definition. Here is an example how to do it.

    dependency.h

    #ifndef DEPENDENCY_H
    #define DEPENDENCY_H
    
    class Dependency
    {
    public:
        //...
        int foo();
        //...
    };
    
    #endif // DEPENDENCY_H
    

    caller.cpp

    #include "dependency.h"
    
    int bar(Dependency& dependency)
    {
        return dependency.foo() * 2;
    }
    

    test.cpp

    #include 
    
    // block original definition
    #define DEPENDENCY_H
    
    // substitute definition
    class Dependency
    {
    public:
        int foo() { return 21; }
    };
    
    // include code under test
    #include "caller.cpp"
    
    // the test
    void test_bar()
    {
        Dependency mockDependency;
    
        int r = bar(mockDependency);
    
        assert(r == 42);
    }
    

    Notice that the mock does not need to implement complete Dependency, just the minimum (used by caller.cpp) so the test can compile and execute. This way you can mock non-virtual, static, global functions or almost any dependency without changing the productive code. Another reason I like this approach is that everything related to the test is in one place. You don't have to tweak compiler and linker configurations here and there.

    I have applied this technique successfully on a real world project with big fat dependencies. I have described it in more detail in Include mock.

提交回复
热议问题