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?
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With