The basic principal of writing a unit tests is that when you do a transaction you know the “expected” result and then you compare with the actual result that was generated, and if these results match you have a passed unit test.
It is always interesting to write unit tests for Database services. Usually the problem that comes to mind is how to exactly predict the state of the database at the time when unit tests are running, so that the unit tests know what to expect. Some people may argue that you can mock out all the database functionality (mock the repositories), this idea may be very applicable in some scenarios but I usually do not go this way because of two reasons,
- It seems like to much work
- Our applications are mostly data driven applications so there is not much to test anyway other than database transactions.
One way of knowing the exact state of the database can be to initialize(create) the database every time the unit tests are run. Once the database is created we might want to insert some initial data which is required for the unit tests.
I have been using Entity Framework Code first in my recent projects. Entity Framework provides you a very good way of achieving the two objectives I have mentioned in the previous paragraph.
EF provides a concept of Database initializers, these are implementations which define the strategy of how (rather when) the database will be created using our model (if you are a bit lost then I recommend to watch Code First Development with Entity Framework). These implementations implement an Interface called IDatabaseInitializer. There are some pre-backed strategies for database creation are provided with the EF. The one we are interested here is DropCreateDatabaseAlways. The name says it all, when using this strategy a database will be created every time code is executed(unit tests are run). To use the Initializers all you need to do is to write the following code before your unit tests are executed
(Make sure you are using a local database server(SQL Express), things can really stressed if you are using a shared development server .)
So now our database is created every time unit tests are run, now we need to create some data each time the database is created. For this you can inherit the DropCreateDatabaseAlways class and override a method called Seed. using this method you add the initial records you want to create every time database is created.
Here is how the code will look like
public class MyUnitTestDatabaseInitializer : DropCreateDatabaseAlways<MyDbContext>
protected override void Seed(WilkeDbContext context)
//you can add any data using the context objected provided in the parameter
The seed method is called just after the database is created by the the framework. Now all you need to do it to tell the framework to use your Database Initializer, and that you will do by modifying the code I wrote above.
System.Data.Entity.Database.SetInitializer<MyDbContext>(new MyUnitTestDatabaseInitializer <MyDbContext>());
so here you have it, now you can write the unit tests which are totally predictable and can run on any environment, be it your local machine or your Build Server.