Test Your NHibernate Mappings!

Disclaimer! Ayende rightly points out that if you are testing your queries you get this mapping test for free. If you aren’t, well put this in place as a stop gap measure (to test mappings) and if you have queries, which you probably do, get to testin’!

A while back Bil Simser put up a post on the first test you should write when using Castle Windsor. In it he shows a technique for verifying his component registrations are correct.

Since Windsor and NHibernate are the peanut butter and jelly of the ALT.NET crowd, I think we can and should do the same for NHibernate:


[Test]
public void Verify_NHibernate_mappings()
{
   string myConfigPath = @"wherever\you\put\your\NHibernate\config.xml";
   Configuration config = new Configuration();
   _sessionFactory = config.Configure(nhibernateConfig).BuildSessionFactory();
}

Would that I did this before today. Yeah, I win the douchey team member award for making a bunch of refactorings (renames mostly) and not fixing the mappings. Remember: Resharper, as great as it is, doesn’t do NHibernate mappings. Of course the unit tests passed so I think I’m fine and move on with my life. The next developer that updates with my commit can’t run the app and gets to clean up my mess. Fun for them!

I’ve learned my lesson. This little screw up illustrates the need for at least some automated integration tests and the lynchpins of many of our architectures — the ORM/IoC tools — seem like easy and high value targets.

This entry was posted in C#, code, NHibernate, testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

15 Responses to Test Your NHibernate Mappings!

  1. I actually blogged about the same kind of thing recently: http://www.connicus.com/archive/2008/02/25/testing-nhibernate-object-mappings-in-isolation-part-2-dependencies.aspx

    I’ve recently refactored to create one test for testing the domain/mapping relationship and another for the map/database schema relationship.

    I will post an update with this info soon..

  2. Dave Laribee says:

    @Thomas – Sweet tip!

  3. Some of the useful data out of NHibernate when you set up your session factory comes out as log4net warnings. One in particular is when you use private setters on your data objects, but there are others.

    To catch these, I have a custom log4net appender derived from their AppenderSkeleton that just adds all logging messages it receives to a list. I set the threshold to Warn, and run through my NH initialization. If any warnings/errors are output, I say the unit test fails.

    Important note if you go this route: I can’t guarantee that log4net will stop writing to a closed/disposed appender. You’re likely to (only sometimes) get an exception thrown for writing to a closed appender if you Dispose() yours. Any hints would be great, but for now I just don’t close my custom appender. It doesn’t hurt anything but memory usage to have it continue to collect logging data while the rest of the test suite runs, and that could easily be fixed by telling it to no longer collect events.

  4. Colin Jack says:

    We have the test you describe and it could be useful, no point running the (relatively slow) persistence tests if the mappings are bad.

  5. Hi Dave,
    as was suggested already you could use the R# NHibernate plugin from http://code.google.com/p/nhplugin/. It has support for renaming of mapped properties and fields. Yesterday I added support for mapped classes, the other type names will follow.
    If you are missing a feature please feel free to drop me a note.

    Cheers,
    Stefan Lieser

  6. Will Shaver says:

    The resharper nhibernate plugin is now on google code here:

    http://code.google.com/p/nhplugin/

    I’ve been using it for about two weeks and find it handy. Not perfect yet, but does save time avoiding obvious spelling errors.

    RelatedCustomer_DataList
    v
    RelatedCustomers_DataList

    etc

  7. Dave Laribee says:

    @Ayende

    Sure. Are the concepts of a) testing your mappings and b) testing your queries mutually exclusive?

    Granted testing your queries automatically tests your mappings but we can get some advantage — if we’re being shameful and not testing queries — by doing the mapping test first.

    Oh, ok, I’ll add a dislaimer at the top. I talked myself into it…

  8. Trey Thornton says:

    See Ben Sheirman’s screencasts for a complete TDD with NH presentation.

  9. Tobin Harris says:

    Nice tip!

    I usually keep a separate test fixture for *just* testing that NHIbernate mappings are working as expected (testing use of entities + associations). That tests my mapping file by default, but I’d not thought of testing it explicitly.

  10. Jason Imison says:

    If you were using NHibernate.Mapping.Attributes, you wouldn’t need to worry about your mapping files being out of sync.

  11. As already mentioned above the resharper nhibernate plugin.

    It is available at http://nhplugin.lieser-online.de/

    and gives you suppport for invalid mappings. Of course you will need the unitttest, but it is nice to have a little bit of resharper support (Although it doesnt refactor the files for you)

  12. Dave,
    You have said that queries are business logic.
    As such, they should be tested. And because DB logic and App logic are different, you need to test them against a DB.

    They cannot be tested if the mapping is broken.

  13. Dave Laribee says:

    @Steve – Sweet! (Potentially.)

  14. >> Resharper, as great as it is, doesn’t do NHibernate mappings.

    I recently came across the ReSharper NHibernate Plugin, but haven’t had a chance to dig into it yet. http://nhplugin.lieser-online.de/

  15. Bil Simser says:

    Thanks Dave. You know, it never occurred to me to post this as well as I have this spec in our projects as well.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>