如何在Google Test中公共方法正在使用的类中模拟私有方法?

时间:2018-10-26 07:46:51

标签: c++ googletest gmock

我有一个类,例如ClassA,它具有一些公共功能和私有功能。 公共功能又将私有功能分类。 现在,我的目的是通过公共功能测试私有功能。 对于Public函数,我试图调用原始实现,对于私有方法,我试图创建一个Mock函数。

我的A类是这样的,

class ClassA {
public:
    string getName(string key) {
        int value = 2;
        int code = getCode(value);
        if(code != 2)
             cout<<"Error";
        else
             return "XYZ";
    }

private:
    int getCode(int value) {
        if(value == 2)
             return 2;
        else
             return -1;
    }
};

现在我有一个像这样的ClassA模拟了,

class MockA : public ClassA {
       public:
       MOCK_METHOD1(getName,string(string key)); //Mock for public method
       MOCK_METHOD1(getCode,int(int value))l //Mock for private method
}

这是我的GoogleTest测试用例,

TEST(ClassATest, Test1)
{
    MockA a;
    Class a1;

    EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(2));
    EXPECT_CALL(a,getName()).Times(1).WillOnce(Return(Invoke(&a1, 
ClassA::getName());
}

如您所见,对于私有方法,我正在使用模拟,对于公共方法,我正在使用Invoke并调用原始实现。

现在,当我编译这段代码时,我得到一个错误,

实际函数调用计数与EXPECT_CALL(a,getCode())不匹配。 预期:将被调用一次 实际:从未致电-不满意和主动

现在,当我尝试对getCode()使用原始实现时也是如此,

EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(Invoke(&a1, 
ClassA::getCode());

我收到一个编译错误,说getCode()无法访问,我认为这是预期的。

现在,如果您正在阅读本文,希望您理解我的问题陈述。 我必须通过我通过gtest测试的公共方法,通过传入不同的参数来测试私有方法。

我想模拟github中this文章中所述的私有方法,并为我的公共方法调用原始的生产代码。

我在根本上做错了吗?如果是这样,你们中的任何一个可以为我的用例提供更好的方法。

我尝试了FRIEND_TEST和tbh,我不想在生产代码中进行任何修改。我会尽力而为。

2 个答案:

答案 0 :(得分:1)

您正在尝试从ClassA调用私有方法。除非有一个朋友声明,否则这是不可能的,但是,这并不理想。

问题源于您的测试设计,该测试应调用公共API而不是实现细节。

答案 1 :(得分:0)

最新答案,但是我目前正在研究类似问题,并且看到了这个问题。

在您的示例中,我不确定Invoke()的用途是什么,但是如果您要尝试做的就是验证对getCode()的调用并控制其返回值,那么您只会需要嘲笑那个。

您将必须修改生产代码以使私有函数虚拟化,因此,如果这不是一个选择,那么这当然对您不起作用。不过,这似乎是一个相当安全的修改。

class ClassA {
public:
    string getName(string key) {
        int value = 2;
        int code = getCode(value);
        if (code != 2)
            return "Error";
        return "XYZ";
    }

private:
    virtual int getCode(int value) {
        if (value == 2)
            return 2;
        return -1;
    }
};

class MockA : public ClassA {
public:
    MOCK_METHOD1(getCode, int(int value));
};

TEST(ClassATest, Test1)
{
    MockA mockA;
    EXPECT_CALL(mockA, getCode(2)).WillOnce(Return(2));
    EXPECT_EQ(mockA.getName("key"), "XYZ");
}