views:

238

answers:

5

Assumptions: We use .NET coding against SQL Server 2005

I was just wondering how most people incorporate state into the Unit Tests that affect their database? I know when and where to use mocking, but when you want to move past that and actually do some database tests... what strategies do you use to setup and teardown your database? Do you do this per test? or setup a certain scenario in the database and run several tests against that "state of the world". Any advice would help. Thanks.

+2  A: 

Here's what I do in NUnit...Start a database Transaction in a method marked with the [Setup] Attribute. Setup the database state as you would like. NUnit then runs the test against that state. Roll back the database transaction in a method marked with the [TearDown] attribute. You never change the state of the database that way.

Jason Punyon
It works, but scales terribly. If the methods your testing already open transactions or open their own connections to the database, your test deadlocks. The worst case scenario is when you have to kill your test process because a deadlock and it leaves an unclosed transaction on the database. Ouch.
Juliet
I understand about the scaling, but I had not thought about using transactions in this way before. +1
tyndall
@Princess: The multiple open connections I could see...But the MSDN article on Nesting Transactions says they should work. I agree that the worst case scenario is bad...but it's a test database...I definitely wouldn't do this on a production server.
Jason Punyon
+4  A: 

I run most of the testcases against an empty database, meaning that only the database schema exists, but no data. The actual data is created and deleted by the test cases or the setup and teardown as needed. This takes longer than having an a prepared database, but is more resistent against database schema changes.

Sebastian Dietz
I like this idea. It'll also catch bugs in code that don't handle the case where a table is empty, as seems to crop up in legacy systems that've been around for a while.
Dana
+1 - Got to test those empty tables. This is basically the model I'm using now. It works ok for me.
tyndall
+2  A: 

First of all, all my Database DDL 'scripts' are written in C# classes. I use Migrator.NET to do this: I have several classes in where every class contains some logic to upgrade or downgrade my DB.

I have a database that is called 'projectname_test' that I use to run my unittests against that need to have DB access. This DB is being upgraded by my Migrator.NET classes. This DB is upgraded by a CI process (CC.NET).

The unittests that access that DB will remove everything that is in that DB after they ran. And, when I want to play it drastically, I can simply drop my test DB; it will be rebuilt by the CC.NET process. :)

Frederik Gheysels
Actually, I've read that it has been updated or some important new features are planned, but I haven't looked at it after I've downloaded.I've written some extensions to it myself to fit my needs.
Frederik Gheysels
+1 - I didn't know about Migrator.NET. What do you know about the project status? I see it has been updated since Aug 05, 2008
tyndall
It looks like it would be easy to extend. I wish this project well, as I don't have much faith in M / Oslo model yet.
tyndall
+1  A: 

Take a look at this question and answers http://stackoverflow.com/questions/321180/how-do-i-test-database-related-code-with-nunit/367294#367294

Mike Two
+1 I'll have to see what MbUnit has that is similar to this.
tyndall
MbUnit has something like the NUnit RollBack attribute. Personally I like the finer grained control of managing the transaction yourself.
Mike Two
+1  A: 

If you use NHibernate as ORM it is easy to swap the real SQL Server database (a few lines in app.config) with an in-memory SQLite database that is easily recreated on every test. This way your integration/build server which will execute the unit tests no longer needs to access an SQL Server.

Darin Dimitrov
+1 wouldn't have thought of that. neat idea.
tyndall