c++ - 使用 Gmock 将真实函数重新路由到模拟函数?

标签 c++ unit-testing testing googletest googlemock

当我研究来自 Google 的 Gmock 时,我已经安装并构建了项目,目前运行良好。但是我对模拟函数有些担心。现在我有以下文件:

<1>myGtest.h

#ifndef MYGTEST_H_
#define MYGTEST_H_

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

#endif /* MYGTEST_H_ */

<2>源代码.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> 测试程序.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();
}

你能帮我解释一下吗:我如何模拟函数 int test(int)?我希望一旦执行 TEST_F(BTest, CallMockTest),程序就会调用 function(99);。然后我的模拟函数 int __wrap_test(int) 将被调用而不是 int test(int)

非常感谢您的回答。

最佳答案

这里的关键思想是要认识到模拟是对象模拟真实对象的行为。这意味着您对它们设置期望(即:它们被调用的次数、使用哪些参数等),并使用模拟来模拟一些操作(即:返回特定值或更改某些参数等)

在您当前的实现中,当您调用 function() 时,它仍然会调用 test() 的真正实现。所以你的 EXPECT_CALL 总是会失败。理想情况下,test() 应该是您要模拟的接口(interface)的一部分。说:

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

注意:为简单起见,我将忽略 MyInterface 的实际实现,因为无论如何我们打算使用我们的模拟来绕过实际实现。

现在,被测函数 function() 理想情况下应该是类的一部分。稍微改变一下你的实现:

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

现在,使用 function() 的第二个参数,您可以传递您创建的 mock。但在此之前,您需要定义您正在模拟 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 中学到很多技巧 CookBook

关于c++ - 使用 Gmock 将真实函数重新路由到模拟函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36450421/

相关文章:

c++ - 在派生类中更改功能访问模式

c++ - 矩阵处理程序大序列

java - 将 Java 程序转换为 C++

android - Instrumentation.ActivityMonitor 不监控 Intent.ACTION_CALL

使用 Capybara 测试渐进增强的功能

ruby-on-rails - 如何在 rspec 请求规范中设置请求 header ?

c++ - 将两个数组复制到一个更大的数组中?

python - 如何将 key 输入终端以进行单元测试

python - 将 Selenium IDE 脚本导入为 unittest.TestCase 并动态修改

python - 为导入的库静音 Pytest 库输出