C++ 使用Gmock将实函数重新路由到模拟函数?
当我从谷歌研究Gmock时,我已经安装并构建了该项目,到目前为止效果良好。但我对模拟函数有些担心。现在我有以下文件: myGtest.hC++ 使用Gmock将实函数重新路由到模拟函数?,c++,unit-testing,testing,googletest,gmock,C++,Unit Testing,Testing,Googletest,Gmock,当我从谷歌研究Gmock时,我已经安装并构建了该项目,到目前为止效果良好。但我对模拟函数有些担心。现在我有以下文件: myGtest.h #ifndef MYGTEST_H_ #define MYGTEST_H_ int test(int); int function(int); #endif /* MYGTEST_H_ */ src_code.cpp #include <stdio.h> #include "myGtest.h" int test(int a) {
#ifndef MYGTEST_H_
#define MYGTEST_H_
int test(int);
int function(int);
#endif /* MYGTEST_H_ */
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;
}
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();
}
#包括
#包括
#包括“src/myGtest/myGtest.h”
#包括“src/dummy/myGtest_dummy.h”
使用测试::;
使用测试::返回;
使用测试::不连续;
使用::testing::至少;
外部内部函数(INTA);
外部内部测试(INTA);
B类测试:公共测试::测试{
公众:
myGtestMock_试验;
int包装试验(INTA);
};
int BTest::uuu包装_u测试(int a){
printf(“覆盖!\n”);
返回a;
}
测试(B测试、CallMockTest){
EXPECT_调用(模拟_测试,测试(0))
.WillOnce(调用(this,&BTest::\uuu wrap\u test));
功能(99);
}
int main(int argc,char*argv[]){
::测试::InitGoogleTest(&argc,argv);
返回运行所有测试();
}
你能帮我解释一下:我如何模拟函数inttest(int)
?我希望在执行TEST\F(BTest,CallMockTest)
后,程序调用函数(99)代码>。然后将调用我的模拟函数int\uu wrap\u test(int)
,而不是int test(int)
非常感谢您的回答。这里的关键思想是要认识到,模拟是对象模拟真实对象的行为。这意味着您对它们设置了期望值(即:调用它们的次数、使用哪些参数等),并使用模拟来模拟某些操作(即:返回特定值或更改某些参数等)
在当前实现中,调用function()时,它仍将调用test()的实际实现。所以你的预期呼叫总是会失败。理想情况下,test()应该是要模拟的接口的一部分。说:
class MyInterface{
public:
...
virtual int test(int a) = 0;
};
注意:为了简单起见,我将忽略MyInterface的实际实现,因为无论如何,我们打算使用我们的mock绕过真正的实现
现在,被测试的函数function()理想情况下应该是类的一部分。稍微更改一下您的实现:
class MyClass{
....
int function(int a, MyInterface * interface){
int x = interface->test(a);
if(x == 0)
return 99;
else
return 0;
}
};
现在,使用function()的第二个参数,可以传递创建的模拟。但在此之前,您需要定义您正在模拟MyInterface:
class myGtestMock : public MyInterface{
....
};
现在,在您的测试文件中:
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
}
你可以从google mock中学到很多技巧非常感谢你抽出时间回答我。我理解你所说的。但是,我的客户只给了我源代码(src_code.c
),我不能编辑它。假设我正在测试function()
,并在function()
中调用test()
。这里的问题,test
非常复杂,所以我想将其作为存根,只想控制存根的返回值和输出参数的值。请参阅此链接:我不能说我理解这里提到的所有内容,但我认为这与您要查找的内容一致。谢谢。我以前研究过这个弱属性。但是,不幸的是,它只创建了一个从实函数到弱函数的链接,一旦我调用实函数,编译器总是将它重新路由到弱函数,我不能再使用实函数了。如此悲伤!
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
}