Search code examples
c++unit-testinggoogletestgooglemock

I am doing unit testing using gtest and gmock frameworks and I need help in stubbing/mocking a external C functions used inside class functions


So I am trying to write test cases for my production code but the coverage is drastically low due to the usage of some external C library which cannot be executed without target hardware, So I have no choice but to stub the same. Now the problem is how to stub a C function ?

My production code : prod_code.cpp

 int TargetTestClass::targetFunc()
 {
    if(externalCFunc() == True)
    {
        statement1; statement2; statement3; /// and so on
    }
 }

My testcode.cpp generally contains tests like this

//Fixture for Target Test class
class TargetTestClassFixture : public testing::Test {
      TargetTestClass* targetTestClassPtr;
      void SetUp() {
         targetTestClassPtr = new TargetTestClass();
      }
      void TearDown() {
         delete targetTestClassPtr;
      }
  };



TEST_F (unitTest, test_001)
  {
       targetTestClassPtr->targetFunc(); //Need to do something here so that externalCFunc() returns true on call
  }

Solution

  • I found 2 solutions to my problem so I am going to answer the same here.

    Solution 1 : This involved changing the target source code. Basically you need to write a wrapper that calls the external C functions like below

    Class TargetTestClass{
        protected:
            int targetFunc();
            virtual int externalCFuncWrapper();  // Wrapper
    };
    
    //call the external C function from the wrapper
    int TargetTestClass::externalCFunctionWrapper(){
        return(externalCFunc());
    }
    
    //Definition of targetFuc in original question
    
    //Now write a mock class for Target Test Class as usual and mock the wrapper function to return what you want to 
    
    class MockTargetTestClass : public TargetTestClass{
        public: MOCK_METHOD0(externalCFunctionWrapper, int());
    };
    
    //Now use the Mock class as needed
    TEST_F ( TargetUnitTest, TestingExternalCFuctionCall)
    {
        MockTargetTestClass mockTargetTestClassObj;
        using ::testing::Return;
        using ::testing::_;
        Expect_Call(mockTargetTestClassObj, externalCFunctionWrapper())
        .WillOnce(Return(1));
    
        Assert_EQ(mockTargetTestClassObj.targetFunc(), 1);
    }
    

    Solution 2 : Thanks to @kreynolds, I have looked into Fake Function Framework and implemented as follows :

    Class TargetTestClass{
        protected:
            int targetFunc();
            //No Code change needed in target source code
    };
    
    //In testcode.cpp 
    
    #include <gmock-global/gmock-global.h>
    
    MOCK_GLOBAL_FUNC0(externalCFunc, int());
    
    TEST( Unittest, test002){
        using ::testing::Return;
        using ::testing::_;
        EXPECT_GLOBAL_CALL(externalCFunc, externalCFunc()).WillOnce(Return(1));
    
        TargetTestClass targetFunc; //This does not contain any wrapper
        EXPECT_EQ(targetTestClassObj.targetFunc(), 1);
    }
    

    I am using the second solution as this does not require any change in my source code and easier to use.

    Once again thank you everyone for giving your time.