One of the interesting features of MbUnit 2.4 is the Rollback attribute. I’ve spoke about this in passing in some of my previous posts, but I thought I would drive a little deep into what is going on.
The Rollback attribute can be added to any test method, when the test has finished (either passed or failed) any changes made to the database is rolled back – even if it has transactions inside. This means that your tests are more isolated
Rollback uses Enterprise services and COM+ and is based on the .Net 1.1 implementation. Rollback2 uses TransactionScope from System.Transactions which was included in .Net 2.0. If your project is using .Net 2.0, Rollback2 would be the preferred attribute to use. An example of how this could be used is:
[Test]
[RollBack]
public void GetCategoryByName_NameOfValidCategory_ReturnCategoryObject()
{
InsertCategory();
Category c = ProductController.GetCategory(“Microsoft Software”);
Assert.AreEqual(“Microsoft Software”, c.Title);
Assert.AreEqual(“All the latest Microsoft releases.”, c.Description);
}
One question I was asked at DDD was if Rollback supports other databases or if its just SQL Server. The answer is, I still haven’t been able to find a definitive answer. In theory it should work, but I have read some forum comments about errors when using TransactionScope. If I can get everything setup, I’ll write another post with my findings.
While looking around about this feature I came across a RestoreDatabase attribute. Had to have a play!
Turns out, it allows a backup to be restored before the test is executed (if you didn’t get it from the name). It gets all the information based on the SqlRestoreInfo attribute at the test fixture level and uses that to store the database before the test is executed.
[TestFixture]
[SqlRestoreInfo(“Data Source=BIGBLUE;Initial Catalog=Master;Integrated Security=True”, “Northwind”, “E:Northwind.bak”)]
public class Class1
{
string connectionString = “Data Source=BIGBLUE;Initial Catalog=Northwind;Integrated Security=True”;
[Test]
[RestoreDatabaseFirst]
public void GetOrders()
{
//string queryString = “DELETE FROM dbo.[Order Details];”; If we execute this in the first run the table is empty.
string queryString = “SELECT * FROM dbo.[Order Details];”; If we execute this in the second run, the data is restored.
string queryString2 = “SELECT * FROM dbo.[Order Details];”;
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
SqlCommand command2 = new SqlCommand(queryString2, connection);
connection.Open();
command.ExecuteNonQuery();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format(“{0}, {1}”,
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
It’s a neat idea and good for integration testing, but I wouldn’t recommend it for unit testing as the additional time to restore the database would soon mount up, expect improvements to testing with databases in MbUnit v3.
Hey Ben,
Just wanted to say that I’m new to MBUnit and your post have been really helpful. Thanks for that. One issue with this post I’m trying to find the SQLRestoreInfo Attribute in MBunit v3 but I can’t seem to find it. I even downloaded the source and searched through it but came up empty. Has this functionality been completed dropped or has it been replaced with something else in v3?
OK, I just noticed that v3 is actually still in alpha, don’t know how I missed that when I originally downloaded it. 🙂 So I guess I’ll switch to v2 and just wait…