Integration tests are a useful tool for building software. Thanks to them we can easily verify whether business logic works well with the underlying infrastructure. Unfortunatelly those tests have a major drawback – they tend to be very slow. In one of our systems we have over 700 integration tests. Total execution time can sometimes exceed 40 minutes. It is way to long to be acceptable for us.
Firstly let’s briefly look into test run procedure. For each test we perform a setup which consists of two main operations:
– Database setup – we need clean database for every test case
– Dependency injection container setup – we want each test to have independent DI container to allow some slight manipulations (e.g. registering a mock object). Just to note we use Unity container.
When setup is finished the actual test is executed and then followed by DI container dispose.
After performing some time measurment we came into conclusion that setting up the container is the most time consuming operation throughout single test execution. To deal with this, we introduced the concept of child container.
Basically what we do is we set up parent container before any test is executed. Then, for each test, we create a child container. That container automatically inherits all parent registrations so we do not need to perform additional setup each time new test is run. In addition we can freely modify child container registrations (with e.g. registering some mocks) as it will not affect the parent. After test is finished we simply dispose child container. That relatively minor change helped decrease test execution time from 40 to about 10 minutes.
During the work with unity child container we have stumbled across some problems. Without going deep into details we will just provide You with our discoveries.
– When registering a types in parent container it is advisable to use HierarchicalLifetimeManager instead of ContainerControlledLifetimeManager. That way we can be sure that instance will be resolved inside child container and not inside parent.
– When working with Unity extensions (e.g. InterceptionExtension or own custom extensions) one need to consider explicity adding those extensions to child container. Without adding it, when we register some types in child container, parent container extensions won’t be applied to them. On the other hand, parent registration will work correctly when resolved from child.
Unity child container can be helpful when struggling with performance problems of Your DI container. You have to be careful though as there are some usage differences between parent and child.