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

时间:2016-05-10 06:06:21

标签: c++ mocking googletest

我有一个班级和成员:

class A
{
    B obj;
public:
    int f(int i){return obj.g(i);}
}

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

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

非常感谢。

3 个答案:

答案 0 :(得分:2)

要执行此操作,请在class A中使用B而不是对象的指针,并在FixtureA中将单位测试类(friend class)设为A

class A
{
    B *obj;
public:
    int f(int i){return obj.g(i);}
    friend class FixtureA;
};

FixtureA.h中,您可以拥有以下代码

class FixtureA
{
public:
    void Testf();
}

FixtureA.cpp

TEST_F(FixtureA , Testf)
{
    Testf();
}

void FixtureA::Testf()
{
    A objA;
    objA.obj = new BMock();
    objA.f(2);
}

BMock class中,您可以模拟g()功能。

答案 1 :(得分:1)

您无法使用您拥有的代码执行此操作。您已在A类中对您的依赖项进行了硬编码。为了使模拟成为可能,您必须使用一些依赖注入模式。其中一种可能的方法是为B类提供指针(更聪明),在A构造函数中,您将获得指向B的指针,您将使用该指针初始化内部{ {1}}。这样你就可以在测试中放置一个模拟对象。

答案 2 :(得分:1)

您需要使用依赖注入来实现此目的。为此,让类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
    }
};

此外,要在类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); }
};

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

B b;
A a(&b);

在测试阶段,您创建一个模拟类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);
}