In unserer Test-basierten Entwicklung hat sich die Verwendung von Setup-Klassen für unsere Entities etabliert. Unsere Tests sehen folgendem sehr ähnlich:
[Test]
public void FetchJoinTest()
{
var cat = _categorySetup.GetPersisted();
var pitch = _pitchSetup.GetPersisted(p => { p.Categories.Add(cat); return p; });
var reserv1 = _reservationSetup.GetPersisted(r =>
{
r.Pitch = pitch;
r.DateFrom = new DateTime(2009, 10, 31);
r.DateTo = new DateTime(2009, 11, 13);
return r;
});
pitch = _pitchService.GetById(pitch.Id);
Assert.That(pitch.Reservations.Count, EqualTo(2));
}
Leider funktioniert der Test so nicht - er schmeißt eine AssertionException, da pitch.Reservations
keine Elemente enthält.
Warum nicht???
Nach langem hin und her, bin ich mir endlich sicher, es verstanden zu haben: es liegt an NHibernate's Entity-Cache! Da das Pitch-Objekt ja zum Zeitpunkt der Abfrage
pitch = _pitchService.GetById(pitch.Id);
noch in der aktuellen Session geladen ist (was NHibernate meines Wissens nach anhand der ID feststellt), wird kein neues Objekt vom Typ Pitch instanziiert, sondern das schon existierende, pitch
, zurückgegeben. Dieses enthielt aber noch keine Reservierungen zum Zeitpunkt der Persistierung - und so, wie es aussieht, werden diese auch nicht nachträglich geladen (für ein Objekt, das schon in der Session lebt).
Die Lösung ist jetzt gar nicht mehr so schwer: wir schmeißen das vorhandene Objekt einfach weg! Dafür gibt es Session.Evict()
:
[Test]
public void FetchJoinTest()
{
var cat = _categorySetup.GetPersisted();
var pitch = _pitchSetup.GetPersisted(p => { p.Categories.Add(cat); return p; });
var reserv1 = _reservationSetup.GetPersisted(r =>
{
r.Pitch = pitch;
r.DateFrom = new DateTime(2009, 10, 31);
r.DateTo = new DateTime(2009, 11, 13);
return r;
});
_nHibernateHelper.Session.Flush();
_nHibernateHelper.Session.Evict(pitch);
pitch = _pitchService.GetById(pitch.Id);
Assert.That(pitch.Reservations.Count, EqualTo(2));
}
Jetzt läuft der Test mit Erfolg durch. Happy Coding!