Unit Testing NHibernate DALs - What Are You *Really* Testing?

posted @ Thursday, May 17, 2007 10:18 AM

 

Someone new to NHibernate recently asked me how to unit test their data access layer which uses NHibernate.  I've already sent him my thoughts on it, but figured it may make for a good blog post to get some of the community's reaction. 

What Are You *Really* Testing?

From my perspective, there are (at least) a couple questions you should always be asking yourself when practicing TDD or just testing in general:

  1. What am I really testing here?  My code or 3rd party/framework code? 
    • At some point you need to trust the frameworks your using or else you’ll end up testing the whole .NET framework…   Not good!
  2. How much value is really being gained from this test that I am writing?  A quick quiz...
    • Which test do you think would bring the most value?
      • a) A unit test which uses a mocked ISession to verify that when Save(entity) is called that NHibernate does what it's supposed to do?
      • b) A unit test to make sure NHibernate is generating the correct sql for an HQL query or Criteria call which it's supposed to do?
      • c) An integration test which verifies that the mapping files you've written are configured correctly to map your domain objects to your database tables?
    • Answer?  More than likely, C is probably the best answer to this question.  If all you have are unit tests with no state-based integration tests, that's probably a bad sign.  At some point you've got to write integration tests to make sure all your components work together, especially in your data access/persistence layer.

Exceptions

Now, if for some reason you have another layer of abstraction in there like PersonRepository -> IPersistenceFacade -> NHibernate, then driving out the interaction between your PersonRepository and IPersistenceFacade is probably a good idea.  But that's probably as far down as I'd go for unit tests.

Also, if you're not using an ORM and have to use vanilla ADO.NET to hand roll your own data access/mapping layers, then I would most definitely recommend driving that out using TDD and unit tests.  But hopefully this is not something you're having to do for the most part.

Final Thoughts

So far in my current project, I'm only using integration tests for my persistence layer (aka DAL) to verify that my mapping files are correct.  The nice thing is that NH makes this really easy with its SchemaExport tool to very easily generate your database schema from your mapping files.  So I’m using that along with a couple hand-rolled utilities and factories for generating and inserting sample data to use for integration testing purposes.

Of course, having automated unit tests for as much of your application as possible is still a great goal, but sometimes it needs to be weighed against how much business value it’s going to help you deliver in terms of increasing the maintainability and testability of your code.  However, when in doubt, write a test!

Your Thoughts?

Comments
joeyDotNet - 5/17/2007 1:29 PM
# re: Unit Testing NHibernate DALs - What Are You *Really* Testing?
Hi Billy,
Yeah, actually it was after I saw your "default asp.net architecture" article that I started keeping my Repository Interfaces (same as your DAOs) in my Domain Model project. That way the interface is separated and, if needed, I can inject them into my domain objects, although I rarely see this as necessary.

So I use a similar approach using the Repository pattern/language. I'll usually have an IRepository with methods like FindById, FindAll, Save, etc. And then create specialized repositories like IPersonRepository which inherit IRepository and have custom methods when necessary.

This way, when I drive out my "service" layer via TDD, I can inject the appropriate repository and do interaction-based testing to make sure the appropriate repository methods are being called.

So I guess the main thing is that I'll usually only do interaction-based testing against my repository interfaces. Anything below that is usually a database integration test.
joeyDotNet - 5/22/2007 8:41 AM
# re: Unit Testing NHibernate DALs - What Are You *Really* Testing?
Joe,
Oh sure, absolutely. When I was first learning NHibernate, and as I continue to learn, I write all kinds of funky tests to just try stuff out. No harm in that at all.

There are probably a number of ways you could approach the idea of an OrderStatus as you described.

One possibility (off the top of my head) is that if you always know there are going to be 5 order statuses, then create a value object which exposes them and maybe use something similar to the Flyweight pattern to make sure the user of the API is always using a preconstructed instance of that particular OrderStatus.

At that point you can just mark the constructor private to prevent anyone else from creating new instances of it.

Then you could even expose a property like OrderStatus.AllStatuses for grabbing a list of those preconstructed OrderStatus instances for lookup purposes.

Of course, that's just one of many ways you could do it. A lot would depend on the project...
Post Comment






Please add 4 and 5 and type the answer here: