How to mock a member variable of dependency?

て烟熏妆下的殇ゞ 提交于 2021-01-28 14:34:43

问题


I've got a class and member:

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

Here "B obj" is a dependency that requires run-time creation from a file. In my unit test for class A, I wish to mock "B obj", with a function g typed int(int).

How can I write my test code, to mock "B obj", and then test A::f.

Thanks a lot.


回答1:


You need to use dependency injection to achieve this. To this end, have class B inherit from an interface, and have class A hold a pointer to that interface:

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

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

Also, to enable dependency injection in class A, add appropriate constructor or setter method:

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); }
};

Now, in your production code you create an object of class B and pass it to class A object (assuming that we are using the constructor for injection):

B b;
A a(&b);

During testing phase, you create a mock class BMock and pass an object of that class to class A object:

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);
}



回答2:


To do this, take a pointer of B instead of object in class A and make your unit Test class (FixtureA ) as friend class in A.

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

In FixtureA.h you can have following code

class FixtureA
{
public:
    void Testf();
}

In FixtureA.cpp

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

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

In BMock class , you can mock the g() function.




回答3:


You can't do it with the code you have. You have hardcoded your dependency inside the A class. To make mocking possible you have to use some of the dependency injection patterns. One of the possible ways is to have a pointer(better smart) to your B class and in the A constructor you will get a pointer to B with which you will initialize your inner B*. That way you will be able to put a mocked object in your tests.



来源:https://stackoverflow.com/questions/37130444/how-to-mock-a-member-variable-of-dependency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!