views:

112

answers:

3

Suppose I have a C++ class like so:

class A
{
    public:
        A()
        {

        }

        void SetNewB( const B& _b ) { m_B = _b; }

    private:
        B m_B;
}

In order to unit test something like this, I would have to break A's dependency on B. Since class A holds onto an actual object and not a pointer, I would have to refactor this code to take a pointer. Additionally, I would need to create a parent interface class for B so I can pass in my own fake of B when I test SetNewB.

In this case, doesn't unit testing with dependency injection further complicate the existing code? If I make B a pointer, I'm now introducing heap allocation, and some piece of code is now responsible for cleaning it up (unless I use ref counted pointers). Additionally, if B is a rather trivial class with only a couple of member variables and functions, why introduce a whole new interface for it instead of just testing with an instance of B?

I suppose you could make the argument that it would be easier to refactor A by using an interface. But are there some cases where two classes might need to be tightly coupled?

A: 

Depending on how you use B you may be able to use a std::auto_ptr instead of a ref-counted pointer. So long as you don't need to pass a reference to B to something else that would work and require minimal code changes.

tloach
+6  A: 

I think you're taking the idea of Unit Testing too far. In this case, A and B are one unit, i.e., A can't exist without B. First, test B and make sure it passes all of the B-specific unit tests, then once that passes, test A and make sure it behave how it's supposed to.

miked
Interesting, I guess I was picturing that unit tests required all classes to be completely decoupled from each other. But as you point out, A absolutely needs B to work; so they're actually one unit.
lhumongous
A: 

If B is really a dependency injected into A then you should consider a number of other options. First is injecting B at construction time:

class A
{
    public:
        A( const B& _b ) : m_B(_b) {}

    private:
        const B& m_B;
};

If you really want to modify B during the lifecycle of your A object, then ask yourself if you're really the owner of B. If not, pass a pointer to it and assume the one who passes it is responsible for its lifecycle -- this is a tricky route though, and might require you to use ref-counted pointers.

If what you want to do is take a copy of B for yourself then you could define a clone() method on B. If you want to create your own object using information contained in B then you can inject a MyBFactory in the constructor and use it with this B.

Philippe Beaudoin