I have used Unity for my last project and was generally pleased. But benchmarks have me thinking I may go with Simple Injector for my next project.
However, Simple Injector does not seem to have an interface for its Container
class. This means that anytime I want to use the container in a method, I cannot mock the container for unit testing.
I am confused how a tool that really functions based of interfaces, would not itself make an interface to the container. I know that the classic methods of dependency injection do not need the container for anywhere more than the startup. (The rest uses constructor injection.) But I have found that when the rubber hits the road that cannot always be true. Sometimes you just need the container in order to do a "resolve" in the code.
If I go with Simple Injector then that code seems to gets harder to unit test.
Am I right? Or am I missing something?
Simple Injector does not contain an IContainer
abstraction, because:
It would be useless for Simple Injector to define it,
because in case of depending on IContainer
instead of Container
, your code would in that case still depend on Simple Injector, and this causes a vendor lock-in, which Simple Injector tries to prevent.
Any code you write, apart from the application's Composition Root, should not depend on the container, nor on an abstraction over the container. Both are implementations of the Service Locator anti-pattern.
You should NOT use a DI library when unit testing. When unit testing, you should manually inject all fake or mock objects in the class under test. Using a container only complicates things. Perhaps you are using a container, because manually creating those classes is too cumbersome for you. This might indicate problems with your code (you might be violating the Single Responsibility Principle) or your tests (you might be missing a factory method to create the class under test).
You might use the container for your integration tests, but you shouldn't have that many integration tests in the first place. The focus should be on unit tests and this should be easy when applying the dependency injection pattern. On top of that, there are better ways of hiding the container from your integration tests, compared to depending on a very wide library-defined interface.
It is trivial to define such interface (plus an adapter) yourself, which justifies not having it in the library. It is your job as application developer to define the right abstractions for your application as stated by the Dependency Inversion Principle. Libraries and frameworks that tend to do this will fail most of the time in providing an abstraction that works for everyone.
The library itself does not use that abstraction and a library should, according to the Framework Design Guidelines, in that case not define such abstraction for you. As stated in the previous point, Simple Injector would get the abstraction wrong anyway.
Last but not least, the Simple Injector container does actually implement System.IServiceProvider which is defined in mscorlib.dll and can be used for retrieving service objects.
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