Search code examples
c++function-pointersgooglemock

How to assign gmock function to specific function pointer?


I'm working on unit testing two dlls with Gtest and Gmock in C++:
A.dll and B.dll, both are written in C and I cannot modify them.

A.dll's init function uses B.dll's functions as arguments via function pointers. I want to mock B's functions (as they are hardware dependent).

I created a test fixture class for A.dll that dynamically loads the functions init and calc. The following code gives a quick overview of the functions of interest:

class TestFixture : public ::testing::Test {
    // dynamically loads functions from A.dll and assigns
    // them to function pointers init_ptr and calc_ptr.
};

// function pointer typedef for use with B.dll's functions
typedef int (*funcPtr)(int, int);

// Loaded from A.dll    
void init(funcPtr func1, funcPtr func2) {
    // internally set functions in A.dll to be used in calculate
}

// Loaded from A.dll
int calculate(int a, int b) {
    // returns a+b + a+b
    return func1(func2(a,b), func2(a,b));
}

// Inside B.dll, should be mocked
int add(int a, int b) { return a+b; }

// Dummy class for B.dll
class B {
    virtual ~B() {}
    virtual int add(int a, int b) = 0;    
};

class MockB : public B {
virtual ~MockB() {}
    MOCK_METHOD(int, add, (int a, int b));
};

// Following example test run is the goal:
TEST_F(TestFixture, AddTest) {
    MockB b;

    // want to use mocked add function here
    init_ptr(mockedAdd, mockedAdd);

    EXPECT_CALL(b, add(_,_)).Times(3);
    EXPECT_EQ(calc_ptr(2,3), 10);
}

When I tried to create a dummy B and a MockB class, I didn't manage to assign the mocked methods to the function pointers that init_ptr(funcPtr, funcPtr) requires. Is there a way to achieve this with Gmock (or a similar framework)?


Solution

  • the easiest solution is to simply declare a static (or free) function that calls the mock.

    class Fixture : public ::testing::Test
    {
    public:
        static int add(int a, int b)
        {
            return mock_.add(a, b);
        }
    
        static MockB mock_;
    };
    
    MockB Fixture::mock_; // static declaration somewhere in .cpp
    
    TEST_F(Fixture, MyTest)
    {
        EXPECT_CALL(mock_, add(_, _));
        init(Fixture::add, Fixture::add);
    }