使用依赖注入模拟C ++类

时间:2011-04-20 06:55:30

标签: dependency-injection mocking googlemock

假设您正在测试课程A,并且其dependency injection B的依赖注入为C
所以你模拟了{{} 1}}但它唯一的构造函数需要注入B,所以你也必须模拟C并将模拟的C注入模拟的C和然后将其注入B?如果您有5个连续的依赖项怎么办?

有哪些替代方案?

我使用Google Mock,因此具体的答案也会有所帮助。

3 个答案:

答案 0 :(得分:6)

Emile有正确的想法,你应该依赖于接口而不是具体的类。所以在你的例子中它将是:

#include <iostream>
using namespace std;

class C {
public:
    int x;
};

class B {
public:
    ~B(){};
    virtual void doSomething() = 0;
};

class ConcreteB : public B{
public:
    ConcreteB(C c) : m_c(c) {}
    void doSomething(){
        std::cout << "HelloWorld" << std::endl;
    }
private:
    C m_c;
};
class A{
public:
    A(B *b): m_b(b){}

    void functionToTestWithSideEffect(){
        m_b->doSomething();
    }
private:
    B *m_b;

};

//#include <gmock/gmock.h>

int main() {
    C c;
    c.x = 42;
    ConcreteB b(c);
    A a(&b);
    a.functionToTestWithSideEffect();
    return 0;
}

在你的测试中,你创建一个不依赖于任何类C的模拟B.然后你只用B测试接口。这样你就打破了A对C的依赖。创建一个不依赖于它的模拟B. C非常简单:

class MockB : public B {
 public:
  MOCK_METHOD0(doSomething, void());
};

答案 1 :(得分:4)

如果更改设计以使类依赖于接口而不是具体类,则可以解决构造函数问题。除了提高可测试性之外,它还可以以更多代码(接口)为代价提高可重用性和可维护性。

答案 2 :(得分:-2)

在这种情况下,您应该通过指针而不是通过引用注入,然后您可以传递NULL指针。假设你的对象确实是一个mock而不是一个假对象,这就行了,因此它对注入的对象没有真正的依赖。

对于boost::shared_ptr,您可以执行以下操作:

boost::shared_ptr<C> null_c_ptr;
MockB mock_b(null_c_ptr);