Search code examples
unit-testingnhibernatefluent-nhibernatenhibernate-mappingnbuilder

Using NBuilder to test NHibernate mappings


I have been using NBuilder for a while in unit tests to simulate in-memory data and it's awesome, then I wanted to use it to test my NHibernate mappings, I thought it was going to be transparent but I can not figure out what I am doing wrong =( it is simply not working

I am planing to test heavily my NHibernate mapping but since I have too many entities I do not want to populate data manually, that's the main reason I want to use NBuilder

just as a quick reference:

        autoConfig.Override<Planet>(x =>
        {
            x.References(y => y.Sun).Cascade.SaveUpdate().Column("Star_id");
        });
        autoConfig.Override<Star>(y =>
        {
            y.HasMany(x => x.Planets).Inverse().Cascade.AllDeleteOrphan();
        });

(If you need I can provide information about the entities and the mappings but I think they are correct since i am able to save my entities when the data is populated manually)

Manually:

using (var session = factory.OpenSession())
using (var tran = session.BeginTransaction())
{
   var star = new Star { Class = StarTypes.B, Color = SurfaceColor.Red, Mass = 323.43, Name = "fu..nny star" };
   star.Planets = new List<Planet>
   {
      new Planet { IsHabitable = true, Name = "my pla", Sun = star }
   };
   session.Save(star);
   tran.Commit();
}

The above code actually works saving both entities to the database correctly meaning that my mappings are correct but now I want to use NBuilder to auto populate testing data like this:

var star = Builder<Star>.CreateNew().Build();
star.Planets = Builder<Planet>.CreateListOfSize(10).All().With(x => x.Sun, star).Build();
session.Save(star);
tran.Commit();

Inspecting the generated entities while debugging look correct to me, I can navigate through them without problems, but then when I want to commit the transaction I get the following error:

Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [CH9_NHibernateLinqToNHibernate.Domain.Planet#00000000-0000-0000-0000-000000000001]

Any thoughts?


Solution

  • I found the problem, basically NBuilder was assigning a value to my Id and NHibernate was considering it 'persisted', and it was trying to update the record instead of create a new one (the error message was not helping me though...):

    var star = Builder<Star>.CreateNew().Build();
    star.Planets = Builder<Planet>.CreateListOfSize(10).All().With(x => x.Sun, star).With(x => x.Id, Guid.Empty).Build();