Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting dependencies into tests

Usually when using dependency injection, unit (and other) tests are responsible for creating/mocking dependencies of the system-under-test and injecting them.

However, sometimes the test itself has dependencies, or needs to inject dependencies into the SUT that it can't itself create. For example, when testing classes which interact with a database, the test needs to know connection strings and catalog names etc., which can't be hard-coded since they aren't necessarily the same for everybody running the test.

So, how would you recommend that a test find out these settings? Do some xUnit-style test frameworks provide a way to give dependencies to a test fixture? Should the test class have static properties you populate before running all the tests? Should the test ignore DI practices and just go and get the dependencies from some global place? Other suggestions?

like image 689
Wesley Hill Avatar asked Feb 11 '10 12:02

Wesley Hill


People also ask

Is it possible to use dependency injection in unit tests?

Every time you make a change to your constructor, you have to revisit all test cases and rewrite them. It does not matter whether or not that new dependency is part of your test. Wouldn’t it be nice to be able to use dependency injection in unit tests? Well this is in fact possible with Autofixture.

What is the use of dynamic dependency injection?

Dependency Injection is a way of injecting the dependencies into your class. Your class declares it’s dependencies (e.g. via a constructor parameter) and whoever is using your class can provide those dependencies. This way we don’t hard-code dependencies into our classes and our codebase is a lot more flexible.

Can I use autofixture for dependency injection?

Well this is in fact possible with Autofixture. Autofixture is a testing framework created by Mark Seemann, author of “Dependency Injection: Principles, Practices, Patterns”. He is was also part of the team that developed F#! This guy is crazy smart, and really interesting to listen to.

How many parameters can be injected into a test class?

If a test class constructor, a test method, or a lifecycle method accepts a parameter, the parameter must be resolved at runtime by a registered ParameterResolver. You can inject as many parameters as you want in any order you want them to be.


1 Answers

There's a principle for fully automated tests: you should be able to pull down all the source code from the source control repository and simply run the tests.

Given that the environment (machine) has the correct installation base (i.e. compiler, test framework, database engine if relevant, etc.) the tests are responsible for setting up their Fixture before executing the test cases.

That means that for databases, the tests should

  1. create the database in question
  2. run its tests
  3. delete the database again after the last test case

If, for some reason you can't do that, the only thing you can really do is to have a configuration file in your source control system that contains machine-specific entries for all machines in your testing invironment; e.g. for the machine Tst1 the connection string is one value, but for Tst2 it's another.

This can get ugly really quickly, so it's much easier to have the tests be responsible for Fixture Setup and Teardown, because that means that they can simply use hard-coded values, or values generated on the spot.

This really has nothing to do with DI...

like image 127
Mark Seemann Avatar answered Sep 28 '22 14:09

Mark Seemann