如何模拟依赖的成员变量?

Hin*_*sum 4 c++ mocking googletest

我有一个班级和成员:

class A
{
    B obj;
public:
    int f(int i){return obj.g(i);}
}
Run Code Online (Sandbox Code Playgroud)

B obj是一个需要从文件运行时创建的依赖项。在我的 A 类单元测试中,我希望使用类型为的B obj函数来模拟。gint(int)

我如何编写测试代码来模拟B obj,然后测试A::f

多谢。

Mar*_*vic 6

您需要使用依赖注入来实现这一点。为此,让类B从接口继承,并让类A保存指向该接口的指针:

class IB
{
public:
    virtual void g(int i) = 0;
};

class B : public IB
{
public:
    void g(int i) {
        // this is your real implementation
    }
};
Run Code Online (Sandbox Code Playgroud)

另外,要在 class 中启用依赖注入A,请添加适当的构造函数或 setter 方法:

class A
{
private:
    IB *obj;
public:
    A() : obj(nullptr) {}
    // You don't need both the constructor and setter, one is enough
    A(IB *pB) : obj(pB) {}
    // void setB(IB *pB) { obj = pB; }
    int f(int i) { return obj->g(i); }
};
Run Code Online (Sandbox Code Playgroud)

现在,在生产代码中创建一个类对象B并将其传递给类A对象(假设我们使用构造函数进行注入):

B b;
A a(&b);
Run Code Online (Sandbox Code Playgroud)

在测试阶段,您创建一个模拟类BMock并将该类的对象传递给类A对象:

class BMock : public IB
{
public:
    MOCK_METHOD1(g, int(int));
};

TEST(ATests, TestCase1)
{
    BMock bmock;
    A a(&bmock);

    // Now you can set expectations on mock object, for example that g will
    // return 100 when it receives 50 as argument
    EXPECT_CALL(bmock, g(50)).WillOnce(Return(100));

    // Now act by calling A::f, which will in turn call g from mock object, 
    // and assert on function return value

    ASSERT_EQ(a.f(50), 100);
}
Run Code Online (Sandbox Code Playgroud)