So I’m switching a bunch of custom written DAO’s for SQL server to NHibernate. NHibernate seems almost as good as the regular Java hibernate, so it’s pretty nice. The custom DAO’s were a big pain and this is much nicer and less bug-prone. I wish we would have written unit tests for the old objects, but it was never done. For the NHibernate transition, I decided to implement them. I have always wondered what the best approach was for testing DAO’s, since they affect the persistent data storage, and it’s hard to control the contents of your database. After reading a few articles, I decided the best approach was to have a special database just for testing. The tests tear down and rebuild the database before they run. This can be sort of slow, but it doesn’t seem too bad in our case. So, we end up having the following databases:
- Local development (on each developer’s machine)
- Local testing (on each developer’s machine)
- Continuous Integration dev (shared)
- Continuous Integration testing (shared)
That looks like a lot of databases. I wrote a simple program using the SQLDMO COM object to dump the database schema (from the CI dev copy, making it a canonical source of the schema) every night and commit it to CVS if there are any changes. That was fairly simple to set up and provides you with a schema to build a blank db at any time, which completely automates maintenance of the testing datbases, so we are down to 3 we have to maintain (semi-)manually.
Now, the unit tests can assume the database is empty and create objects in it at will. So far, so good. My initial approach involves one NUnit test object per NHibernate object. I started with one method called NewObjectTest in each test class, where Object is the name of the object. This has multiple Assert statements to check that each property is being persisted, which is considered a bad practice. The alternative seems very tedious, so this trades quicker implementation with less precise test failure reporting.
Everything was going well until I hit the first foreign key constraint. I realized that many of the database objects are heavily dependent on other ones, so that complicates the tests. If Object A is dependent on Object B, then Object A’s test must create an Object B for the FK, which breaks the independence of the tests. It seems like the best way to solve this would be to make the tests run in order and pass objects to each other, but there doesn’t seem to be any facility to do that in Nunit, so I’m still trying to decide what to do.