Unit testing and the database
One of the things that I hate is how many articles recommend to mock the database so that no database calls are made. The reason for this is that database interaction is a performance killer. Second of all it loads the database with tons of repeated test data (unless you perform a cleanup in your test case that is).
I feel that it is invaluable to have your tests hit the database. I have had cases where all of the business rules pass but when it hits the database an exception is thrown. If I had mocked the database I would not know about this. Granted it is slow to do it this way but I would rather be slow than buggy.
As far as loading the database with repeated test data there are a couple of ways around it. The first is to have every test clean its footprint up which is a big pain. The second way is to enlist the test in a distributed transaction, running the test, and then rolling back the transaction. The way I do this is have a base class that all of my tests inherit from and then have the enlist / rollback in the setup and teardown methods respectively. Here is my standard TestBase class
1 Imports NUnit.Framework
2 Imports System.EnterpriseServices
5 Public Class TestBase
8 Public Sub Setup()
9 ' Enter a new transaction without inheriting from ServicedComponent
10 Console.WriteLine("Attempting to enter a transactional context...")
11 Dim config As New ServiceConfig
12 config.Transaction = TransactionOption.RequiresNew
14 Console.WriteLine("Attempt suceeded!")
15 End Sub
18 Public Sub Teardown()
19 Console.WriteLine("Attempting to Leave transactional context...")
20 If (ContextUtil.IsInTransaction) Then
23 End If
25 Console.WriteLine("Left context!")
26 End Sub
27 End Class
The ServiceDomain class is something most people don't know about and is quite handy to ccreate a localized transaction. You can see that it creates a config that requires a new transaction and then calls ServiceDomain.Enter(config). This changes the context of the application to change and participate in a transaction.
In our tear down we check if we are in a transaction with ContextUtil and then Abort the transaction if we are in it. This will cause all of our interactions with anything that can use DTC to rollback.
So now you can test your database and not worry about garbage data all over your system. I like this as when I put an applicaiton into production I can run my tests against it and double check that no enviromental errors occured without introducing garbage data.