1

When I researched Gmock from Google, I've installed and built the project work well so far. But I have some concern about mocking a function. Now I have the following files:

<1> myGtest.h

#ifndef MYGTEST_H_
#define MYGTEST_H_

int test(int);
int function(int);

#endif /* MYGTEST_H_ */

<2> src_code.cpp

#include <stdio.h>
#include "myGtest.h"

int test(int a) {
    printf("NOT overridden!\n");
    return a;
}

int function(int a){

    int x = test(a);
    if(x == 0)
        return 99;
    else
        return 0;
}

<3> myGtest_dummy.h

#ifndef MYGTEST_DUMMY_H_
#define MYGTEST_DUMMY_H_

#include "gmock/gmock.h"
#include "../myGtest/myGtest.h"

class myGtestMock
{
public:
    myGtestMock(){};
    ~myGtestMock(){};
    MOCK_METHOD1(test, int(int));
};

#endif /* MYGTEST_DUMMY_H_ */

<4> test_program.cpp

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/myGtest/myGtest.h"
#include "src/dummy/myGtest_dummy.h"

using testing::_;
using testing::Return;
using testing::InSequence;
using ::testing::AtLeast;

extern int function(int a);
extern int test(int a);

class BTest:public testing::Test{
public:
    myGtestMock mock_test;


    int __wrap_test(int a);
};

int BTest::__wrap_test(int a){

    printf("overridden!\n");
    return a;
}

TEST_F(BTest, CallMockTest) {

    EXPECT_CALL(mock_test, test(0))
            .WillOnce(Invoke(this, &BTest::__wrap_test));

    function(99);
}

int main(int argc, char *argv[]) {

    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Could you help me explain that: How can I mock the function int test(int)? I'd like to expect that once TEST_F(BTest, CallMockTest) is executed, the program call function(99);. Then my mocking function int __wrap_test(int) will be called instead of int test(int).

Thanks so much for the answer.

273K
  • 29,503
  • 10
  • 41
  • 64
Thảo M. Hoàng
  • 1,224
  • 3
  • 20
  • 42

1 Answers1

1

The key idea here is to realize that Mocks are objects mocking the behaviour of real objects. Meaning that you set expectations on them (ie: the number of times they are called, with which arguments, etc), and you simulate some actions using the mocks (ie: returning specific values, or changing some parameters, etc)

With your current implementation, when you call function(), it will still invoke the real implementation of test(). So your EXPECT_CALL will always fail. Ideally, test() should be part of an interface which you want to mock. Say:

class MyInterface{
public:
    ...
    virtual int test(int a) = 0;    
};

Note: for simplicity I will disregard the real implementation of MyInterface, since anyways we intend to by pass the real implementation using our mock.

Now, function() which is the function under test, should ideally be part of class. Changing your implementation a bit:

class MyClass{
    ....
    int function(int a, MyInterface * interface){
        int x = interface->test(a);
        if(x == 0)
            return 99;
        else
            return 0;   
    }
};

Now, using the second parameter of function(), you can pass the mock you created. But before that you need to define that you are mocking MyInterface:

class myGtestMock : public MyInterface{
    ....
};

Now, in your test file:

TEST_F(BTest, CallMockTest) {
    myGtestMock myMockObj;

    //Testing (x==0)
    EXPECT_CALL(myMockObj, test(99))   
    .Times(1)
    .WillOnce(Return(0));       //set the action

    EXPECT_EQ(99,function(99, &myMockObj));
    Mock::VerifyAndClear(&myMockObj); //to clear the expectation

    //testing else
    EXPECT_CALL(myMockObj, test(99))   
    .Times(1)
    .WillOnce(Return(1));       //set the action

    EXPECT_EQ(0,function(99, &myMockObj));
    Mock::VerifyAndClear(&myMockObj); //to clear the expectation
}  

There are many tricks you can learn from google mock CookBook

MIbrah
  • 1,007
  • 1
  • 9
  • 17
  • Thanks so much for your time to answer me. – Thảo M. Hoàng Apr 07 '16 at 14:00
  • I understood what you said. But, my customer only gave me the source code (`src_code.c`) and I must not be editted it. Assume that I am testing `function()` and in `function()`, the `test()` is called. The problem here, `test` is very very complex, so I would like to make it as a stub, and only want to control the _return value_ and value of the _output args_ of that stub. – Thảo M. Hoàng Apr 07 '16 at 14:08
  • See this link: http://stackoverflow.com/questions/19552805/using-google-mock-for-c-code – MIbrah Apr 07 '16 at 14:24
  • I can't claim I understand everything mentioned there, but it looks to me that this is along the lines of what you are looking for. – MIbrah Apr 07 '16 at 14:25
  • Thanks. I researched this **weak** attribute formerly. But, unfortunately, It only creates a link one time from the real function to the weak function, and once I call real function, the complier always re-route it to the weak function, and I can't use the real function any more. So sad! – Thảo M. Hoàng Apr 07 '16 at 14:41
  • Do you know if `test` is a method of your `MyClass` and `function` calls `test`, how to mock `test` ? – Thảo M. Hoàng Apr 09 '16 at 16:17