- Classes are more modular, as they depend only on the interface of passed-in dependencies. Class behavior can be changed by swapping out a new component.
- Testing is simplified, since stubs can be substituted for any dependency.
- It's harder to understand how a class works when reading just that class. You may have to track down its invocation to see what kind of components are passed in.
- Is DepedencyClass.expects(:new).returns(stub)) a smell, since we should have injected that stub to the class that uses it instead?
- If a class uses DI, should one only pass in already-instantiated dependencies, or is it okay to let the calling class instantiate them?
- Am I missing any pros or cons?
It depends on what you mean by: "See what's happening."
Surely we are imagining that there are multiple implementations that might be injected. By that reasoning, to check all "known" / in hand implementations, you're going to have to go to other files or inspect the tests.
But to "see what's happening" in the narrow compass of the implicit expectations of a basic implementation, a default implementation could help quite a bit.
I would guess that since we like small focused classes with limited responsibilities, any default implementation is not going to be a HUGE amount of code.