【问题标题】:Mocking C++ classes with dependency injection使用依赖注入模拟 C++ 类
【发布时间】:2011-04-30 03:55:50
【问题描述】:

假设您正在测试类A,它有一个B 的dependency injection,它的依赖注入为C。
所以你模拟B,但它唯一的构造函数需要一个注入C,所以你是否也必须模拟C,并将模拟的C注入模拟的B,然后才将其注入A?
如果你有5个连续的依赖怎么办? ?

有什么选择?

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

【问题讨论】:

    标签: dependency-injection mocking googlemock


    【解决方案1】:

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

    【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 您能详细说明一下吗?这会消除依赖注入的必要性吗?
    • 它不会删除依赖注入,只是你注入了一个接口。所以编译时只有接口必须在范围内。这减少了耦合,并且(在您的示例中)C 不再出现,因为您不再是具体的 B。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2017-03-08
      • 2020-06-06
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多