In my last post, I mentioned that one problem with my earlier unit tests was their dependency on database access. Having my tests directly dependent on the database created slow-running tests and tests that were prone to failure as the database changed. Over the course of this post, I’m going to demonstrate some of the techniques I have learned that provide the ability to decouple a set of code from using direct database access. Note that the examples are in C#; however, the principles apply to any object-oriented language with a unit testing framework.
For the following approach to work, it assumes that the software will be well-structured in layers. An example would be to separate out the code into Data, Business, and Presentation layers, a standard n-Tier architecture. For our purposes, we’ll work with the Business Layer and how to write a unit test within the business layer that will no longer need direct database access.
Suppose we are implementing a currency converter. There will certainly be some logic and financial calculations that we will want to test. This converter will also need to look up the current exchange rate which we will assume is being stored in the database.
Our CurrencyConverter class would be coded as follows:
As we write a unit test for this method, we will need to find a way to avoid making a database call. To do this, the first step is to modify the data layer so that it provides an interface along with the CurrencyData class.
The interface for CurrencyData is:
Next we would change the CurrencyConverter so that we can pass in the CurrencyData dependency, which will enable us to unit test the CurrencyConverter without the need to actually use the CurrencyData implementation. Our new CurrencyConverter would have the following private variable and constructor:
Now for our unit test, we can inject in a stub implementation of CurrencyData that allows us to test the business layer without the need of the database. A stub is an implementation of a class with hardcoded return values. In our case, we’re only concerned with testing the calculation provided a given exchange rate. So, we can create a stub implementation that will always return the same exchange rate, allowing us to test the calculation. The unit test would look like:
This approach to dependency injection is known as constructor injection. By injecting the dependency, we can now test the business layer without the need to have the database set up or in a specific state.
This approach can be supplemented by using a Dependency Injection Framework such as StructureMap or Unity. These frameworks support the ability to configure and define the dependency relationships for more complex scenarios. These techniques are further enhanced by using a mocking framework such as Moq or RhinoMocks so that the stub implementation for the data access component does not need to be created, but can be generated using the mocking framework. I will examine the usage of a mocking framework, as well as using a Dependency Injection Framework, in future blog posts.
The use of Dependency Injection techniques has become an essential part of how I go about unit testing the applications that I develop. These techniques allow me the ability to focus my tests on the specific layer that I am testing.
- StructureMap - http://docs.structuremap.net/
- Unity - http://unity.codeplex.com/
- Moq - http://www.nuget.org/packages/Moq
- RhinoMocks - http://hibernatingrhinos.com/oss/rhino-mocks