I was trying to find an answer but it seems it's not directly discussed a lot. I have a composition root of my application where I create a DI-container and register everything there and then resolve needed top-level classes that gets all dependencies. As this is all happening internally - it becomes hard to unit test the composition root. You can do virtual methods, protected fields and so on, but I am not a big fan of introducing such things just to be able to unit test. There are no big problems with other classes as they all use constructor injection. So the question is - does it make much sense to test the composition root at all? It does have some additional logic, but not much and in most cases any failures there would pop up during application start. Some code that I have:
public void Initialize(/*Some configuration parameters here*/)
{
m_Container = new UnityContainer();
/*Regestering dependencies*/
m_Distributor = m_Container.Resolve<ISimpleFeedMessageDistributor>();
}
public void Start()
{
if (m_Distributor == null)
{
throw new ApplicationException("Initialize should be called before start");
}
m_Distributor.Start();
}
public void Close()
{
if (m_Distributor != null)
{
m_Distributor.Close();
}
}
Any component that interacts with an external database, files, or the network cannot be checked as part of unit testing. Unit tests primarily test isolated components during the product's early development phase. Developers using frameworks like Nodejs, Angular, etc., employ Unit Testing Frameworks.
What is a Composition Root? Definition. A Composition Root is a (preferably) unique location in an application where modules are composed together. Figure 1. Close to the application is entry point, the Composition Root takes care of composing object graphs of loosely coupled classes.
The answer to the more general question is yes, you should unit test everything you can. Doing so creates a legacy for later so changes down the road can be done with peace of mind. ... Usually, something which is hard to unit test is also poorly designed. Writing for testability means writing for better design.
Unit tests check on the behavior of units. Think of a class as being a unit. Classes, more often than not, have external dependencies. Tests for such classes should not use its real dependencies because if the dependencies have defects, the tests fail, even though the code inside the class may be perfectly fine.
does it make much sense to test the composition root at all?
Would you like to know whether your application is written correctly? You probably do and that's why you write tests. For this same reason you should test your composition root.
These tests however are specifically targeted at the correctness of the wiring of the system. You don't want to test whether a single class functions correctly, since that's already covered by some unit test. Neither do you want to test whether classes call other classes in the right order, because that's what you want to test in your normal integration tests (call an MVC controller and see whether the call ends up in the database is an example of such integration test).
Here are some things you probably should test:
To be able to do this however, you will need to have a verifiable DI configuration.
Do note that not everybody shares this opinion though. My experience however is that verifying the correctness of your configuration is highly valuable.
So testing these things can be challenging with some IoC containers, while other IoC container have facilities to help you with this (but Unity unfortunately lacks most of those features).
Some containers even have some sort of verification method that can be called that will verify the configuration. What 'verify' means differs for each library. Simple Injector for instance (I'm the lead dev for Simple Injector) has a Verify
method that will simply iterate all registrations and call GetInstance
on each of them to ensure every instance can be created. I always advice users you call Verify
in their composition root whenever possible. This is not always possible for instance because when the configuration gets big, a call to Verify can cause the application to start too slowly. But still, it's a good starting point and can remove a lot of pain. If it takes to long, you can always move the call to an automated test.
And for Simple Injector, this is just the beginning. Simple Injector contains Diagnostic Services that checks the container on common misconfigurations, such as the earlier stated 'lifestyle mismatch'.
So you should absolutely want to test, but I'm not sure whether to call those tests "unit tests", although I manage to run those tests in isolation (without having to hit a database or web service).
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