我正在使用 gtest 和 gmock 框架进行单元测试,我需要 stubbing/mocking 在 class 函数内部使用的外部 C 函数方面的帮助
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
所以我正在尝试为我的生产代码编写测试用例,但是由于使用了一些没有目标硬件就无法执行的外部 C 库,覆盖率非常低,所以我别无选择,只能将相同的存根.现在的问题是如何存根 C 函数?
我的生产代码:prod_code.cpp
int TargetTestClass::targetFunc()
{
if(externalCFunc() == True)
{
statement1; statement2; statement3; /// and so on
}
}
我的testcode.cpp通常包含这样的测试
//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
}
您可以创建一个类似 my_c_stubs.c 的源文件,您可以在其中基本实现 C 函数。例如,实现可以只是 return true。然后不要 link 带有外部 C 函数的原始源文件,而是使用你的存根文件。你应该还是用原来的Cheader。通过这种方式,您将无法存根内联函数。如果需要,则需要一些更复杂的方法。
我找到了 2 个解决问题的方法,所以我将在这里回答同样的问题。
解决方案 1:这涉及更改目标源代码。基本上你需要编写一个包装器来调用外部 C 函数,如下所示
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);
}
解决方案 2:感谢@kreynolds,我研究了 Fake Function Framework 并实现如下:
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);
}
我正在使用第二种解决方案,因为它不需要对我的源代码进行任何更改并且更易于使用。
再次感谢大家的宝贵时间。
所以我正在尝试为我的生产代码编写测试用例,但是由于使用了一些没有目标硬件就无法执行的外部 C 库,覆盖率非常低,所以我别无选择,只能将相同的存根.现在的问题是如何存根 C 函数?
我的生产代码:prod_code.cpp
int TargetTestClass::targetFunc()
{
if(externalCFunc() == True)
{
statement1; statement2; statement3; /// and so on
}
}
我的testcode.cpp通常包含这样的测试
//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
}
您可以创建一个类似 my_c_stubs.c 的源文件,您可以在其中基本实现 C 函数。例如,实现可以只是 return true。然后不要 link 带有外部 C 函数的原始源文件,而是使用你的存根文件。你应该还是用原来的Cheader。通过这种方式,您将无法存根内联函数。如果需要,则需要一些更复杂的方法。
我找到了 2 个解决问题的方法,所以我将在这里回答同样的问题。
解决方案 1:这涉及更改目标源代码。基本上你需要编写一个包装器来调用外部 C 函数,如下所示
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);
}
解决方案 2:感谢@kreynolds,我研究了 Fake Function Framework 并实现如下:
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);
}
我正在使用第二种解决方案,因为它不需要对我的源代码进行任何更改并且更易于使用。
再次感谢大家的宝贵时间。