Mocking C++ classes with dependency injection

后端 未结 3 1769
没有蜡笔的小新
没有蜡笔的小新 2021-01-15 04:20

Say you\'re testing class A and it has a dependency injection of B which has a dependency injection of C.
So you mock B

相关标签:
3条回答
  • 2021-01-15 04:30

    In this case you should inject by pointer and not by reference, then you could pass a NULL pointer. This would work assuming you're object is indeed a mock and not a fake object, therefore it has no real dependency on the injected object.

    For boost::shared_ptr you could do the following:

    boost::shared_ptr<C> null_c_ptr;
    MockB mock_b(null_c_ptr);
    
    0 讨论(0)
  • 2021-01-15 04:34

    If you change the design so that the classes depend on interfaces instead of concrete classes, you get rid of the constructor problems. Besides improving testability, it may also improve reusability and maintainability, at the cost of more code (interfaces).

    0 讨论(0)
  • 2021-01-15 04:36

    Emile has the right idea, you should depend on interfaces not concrete classes. So in your example it would be something like:

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

    In your tests you create a mock B which does not rely on any class C. Then you are only testing the interface with B. In this way you break A's dependency on C. Creating a mock B that doesn't depend on C is pretty simple:

    class MockB : public B {
     public:
      MOCK_METHOD0(doSomething, void());
    };
    
    0 讨论(0)
提交回复
热议问题