Jonhtra
Jonhtra

Reputation: 947

Google Mock unit testing static methods c++

I just started working on unit testing (using BOOST framework for testing, but for mocks I have to use Google Mock) and I have this situation :

class A
{
static int Method1(int a, int b){return a+b;}
};

class B
{
static int Method2(int a, int b){ return A::Method1(a,b);}
};

So, I need to create mock class A, and to make my class B not to use real Method1 from A class, but to use mock.

I'm not sure how to do this, and I could not find some similar example.

Upvotes: 26

Views: 52213

Answers (3)

BЈовић
BЈовић

Reputation: 64223

You could change class B into a template :

template< typename T >
class B
{
public:
static int Method2(int a, int b){ return T::Method1(a,b);}
};

and then create a mock :

struct MockA
{
  static MockCalc *mock;
  //This class is passed as template type during class B object creation in unit test environment
  static int Method1(int a, int b){ return mock->Method1(a,b);}
};
class MockCalc {
 public:
  MOCK_METHOD2(Method1, int(int,int));
};

Before every test, initialize the static mock object MockA::mock.

Another option is to instead call directly A::Method1, create a functor object (maybe std::function type) in class B, and call that in the Method2. Then, it is simpler, because you would not need MockA, because you would create a callback to MockCalc::Method1 to this object. Something like this :

class B
{
public:
static std::function< int(int,int) > f;
static int Method2(int a, int b){ return f(a,b);}
};

class MockCalc {
 public:
  MOCK_METHOD2(Method1, int(int,int));
};

and to initialize it :

MockCalc mock;
B::f = [&mock](int a,int b){return mock.Method1(a,b);};

Upvotes: 37

Zhiyi-Z
Zhiyi-Z

Reputation: 11

A variant version based on BЈовић's answer that allows not to use template (and error-prone explicit template specialization if your implementation is not in the header files). However, this will need to make the class A not static anymore.

First, create an interface class

class AIf
{
int Method1(int a, int b) = 0;
};

Let your class A implements AIf

class A : AIf
{
int Method1(int a, int b){return a+b;}
};

Then in your class B, add a static pointer to the AIf

class B
{
static AIf* impl = nullptr;
static int Method2(int a, int b) {return impl->Method1(a, b)}
};

When GMock, just do

class MockA : AIf {
MOCK_METHOD2(Method1, int(int a, int b));
};

Then in your tests, set the impl before calling any functions

MockA mockA;
EXPECT_CALL(...);

B::impl = &mockA;
B::Method2(a, b);

Upvotes: 1

Hyugrae Cho
Hyugrae Cho

Reputation: 21

jomock is one of the feasible solutions for Windows application case

class A
{
public:
    static int Method1(int a, int b) { return a + b; }
};

class B : public A
{
public:
    static int Method2(int a, int b){
        return A::Method1(a, b);
    }
};


TEST(JoMock, Method1Test)
{
    EXPECT_CALL(JOMOCK(A::Method1), JOMOCK_FUNC(_, _))
        .WillRepeatedly(Return(3));

    EXPECT_EQ(B::Method2(1, 3), 3);
}

B::Method2(1, 3) returns 3 in this case.

Upvotes: 2

Related Questions