Terry Thibodeau's Blog

Welcome to Terry Thibodeau's Blog Sign in | Join | Help

Testing NHibernate object mappings in isolation

The other day, I found myself creating a bunch of new NHibernate object mapping files for the project I'm working on now. To test these, I had created a simple test case to ensure that the mapping files were valid by invoking BuildSessionFactory on the Configuration object (with the appropriate assemby containing the mapping files specified in AddAssembly). This is all fine and good, but if you have multiple mapping files being tested in one test, it's not a very isolated test. I set out to break up my mapping file tests into separate test cases. This proved to be a pain in the ass, simply because of the confusion I had around loading a single mapping file into the configuration.

There are many ways to initialize an NHibernate session with your class mappings (AddAssembly, AddClass, AddResource, AddFile, AddDirectory, AddInputStream....), but I wanted to get the "automatic" discovery functionality that you get when using AddClass or AddAssembly for a single mapping file (*.hbm.xml). I thought this would be a simple, straight-forward exercise.

What I wanted to do was specify a single Class.hbm.xml file to load and validate against the persistent class to which it is mapped. After reading through the NHibernate docs, I figured that AddResource would probably be my best bet as it lets me specify a direct path to the resource (in this case a mapping file). The AddResource signature looks like so:

/// <summary>

/// Adds the mappings in the resource of the assembly.

/// </summary>

/// <param name="path">The path to the resource file in the assembly.</param>

/// <param name="assembly">The assembly that contains the resource file.</param>

/// <returns>This configuration object.</returns>

public Configuration AddResource(string path, Assembly assembly)

After unsuccessfully attempting many different naming conventions for the path and scouring the documentation and the 'net for documentation, I finally resorted to the NHibernate source for the answer (man, I love open source software :) ). It turns out that NHibernate is using the Assembly class's GetManifestResourceStream() method in AddResource. After reading a couple of others' posts about having trouble with the syntax for GetManifestResourceStream(), I decided to do a couple tests to see what was going on here.

I like to create a separate project specifically for NHibernate resources. Keeping with this convention, I setup a test project (see image below) to test the resource path requirements.

NHibernate Mapping file project  Embedded Resource
Note: the hbm.xml files need to be set as Embedded Resource for AddResource to find them

By calling GetManifestResourceNames() on my ResourceTesting.NHibernateMappings assembly, you can see what format that GetManifestResourceStream() is expecting:

Console Output
ResourceTesting.NHibernateMappings.Subfolder.ClassMapping.hbm.xml
ResourceTesting.NHibernateMappings.ClassMapping.hbm.xml

Armed with the knowledge of the resource path syntax, I can now create a test to load a single mapping file from an assembly using NHibernate's AddResource method with the proper path syntax. Here's a sample test. I will likely refactor this for reuse to allow mapping file path inference based on the persistent class type, but this demonstrates the concept.

[Test]

public void Should_map_single_class()

{

  Assembly assembly = Assembly.Load("ResourceTesting.NHibernateMappings");

  configuration = configuration.AddResource("ResourceTesting.NHibernateMappings.ClassMapping.hbm.xml", assembly);

 

  Assert.AreEqual(configuration.ClassMappings.Count, 1);

  // NHibernate won't try to map to the persistent class

  // unless you BuildSessionFactory

  configuration.BuildSessionFactory();

}

The thing that bugs me about the GetManifestResourceStream call is that you call it on an Assembly instance. Why not have this call infer the fully-qualified resource path from the instance? Then, I could just pass in the resource name. There are probably reasons of which I'm not aware for the decision not to infer the full path, so in lieu of this being implemented in the .NET framework or NHibernate, I hope this helps someone else struggling with resources and NHibernate.

As a side note, I thought that the "Namespace Provider" property on my resource project's subfolder would play a part in the resource path, but it turns out that this is a Resharper addition. See David Laribee's post about it here.

Published Thursday, February 21, 2008 1:22 PM by Terry Thibodeau
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Terry Thibodeau's Blog said:

I thought I should post an update to " Testing NHibernate object mappings in isolation " as that post

February 25, 2008 2:14 PM
 

enrique said:

Thank you, thank you, thank you. I know this post is over a year old now, but I _had_ to express my gratitude for posting this. I've been struggling with this issue for days now and couldn't seem to find anything on this by googling.

I find it odd that there's no official documentation on this since I'm sure you and me ain't the only two people that have unit tests in a separate project.

Cheers!

March 31, 2009 2:38 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit
Powered by Community Server (Personal Edition), by Telligent Systems