3

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)?

273K
  • 29,503
  • 10
  • 41
  • 64
Daniel
  • 45
  • 1
  • 9
  • Looks like you have messed up something with your problem. Unit test should test your code not external code (dll), so thing you are testing looks weird. I would expect that you have some code which is using dll functionality and for test purposes you are using mock of functionality delivered by that dll. So your code could be tested against scenarios which are hard to reproduce when dll is in use. Please provide more context since looks like you are doing something wrong or misunderstood what are mocks for. – Marek R Jul 17 '19 at 10:03
  • The goal is to provide a framework to test dllA that has dependencies in dllB that relies on hardware. – Daniel Jul 17 '19 at 11:22
  • Is this your dll? I mean do you have a code for that dll? – Marek R Jul 17 '19 at 11:39
  • No, I don't have access to the source. I'm only providing a testing framework preferably with mock functionality included. – Daniel Jul 17 '19 at 12:14
  • So what are you testing someone else code? What is the point? The only case I can imagine this has some reason is creating test which will verify that dll functionality didn't change when you deploy new version of it since you do not trust the vendor. But this is quite unusual case. – Marek R Jul 17 '19 at 12:45
  • In normal situation you write test for your code and mock everything what is not yours, so external dll libraries and so on. The gain is that mocks can simulate unusual situations which can araise on dependency (dll or other library). – Marek R Jul 17 '19 at 12:49
  • It is unusual, I definitely agree :) – Daniel Jul 17 '19 at 12:51

1 Answers1

5

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);
}
local-ninja
  • 1,198
  • 4
  • 11
  • I tried your approach but I got ```undefined reference to `Fixture::mock_` ``` during linking. Not sure why, but I'll keep on trying. – Daniel Jul 17 '19 at 12:16
  • @Daniel the mock is static. static members have to be declared somewhere in your source files. I updated the answer. – local-ninja Jul 17 '19 at 12:36
  • Thank you fdan, I should've known that error message by now. It works now, just as you suggested! Do you have any recommendation how to apply this procedure to a long list of varying functions? – Daniel Jul 17 '19 at 13:05
  • This [answer](https://stackoverflow.com/a/32274666/7262963) now makes much more sense to me. Though I'm also torn between Gmock and FFF to mock C-functions. – Daniel Jul 18 '19 at 05:39