Ich verwende Castle ActiveRecord für die Persistenz, und ich versuche, eine Basisklasse für meine Persistenz-Tests zu schreiben, die das folgende tun wird:
- Öffnen Sie eine Transaktion für jeden Testfall und rollen Sie sie am Ende des Testfalls zurück, so dass ich für jeden Testfall eine saubere DB erhalte, ohne dass ich das Schema für jeden Testfall neu erstellen muss.
- Bereitstellung der Möglichkeit, meine NHibernate-Sitzung zu flushen und mitten in einem Test eine neue zu erhalten, so dass ich weiß, dass meine Persistenzoperationen wirklich die DB und nicht nur die NHibernate-Sitzung getroffen haben.
Um zu beweisen, dass meine Basisklasse ( ARTestBase
) funktioniert, habe ich mir die folgenden Beispieltests ausgedacht.
[TestFixture]
public class ARTestBaseTest : ARTestBase
{
[Test]
public void object_created_in_this_test_should_not_get_committed_to_db()
{
ActiveRecordMediator<Entity>.Save(new Entity {Name = "test"});
Assert.That(ActiveRecordMediator<Entity>.Count(), Is.EqualTo(1));
}
[Test]
public void object_created_in_previous_test_should_not_have_been_committed_to_db()
{
ActiveRecordMediator<Entity>.Save(new Entity {Name = "test"});
Assert.That(ActiveRecordMediator<Entity>.Count(), Is.EqualTo(1));
}
[Test]
public void calling_flush_should_make_nhibernate_retrieve_fresh_objects()
{
var savedEntity = new Entity {Name = "test"};
ActiveRecordMediator<Entity>.Save(savedEntity);
Flush();
// Could use FindOne, but then this test would fail if the transactions aren't being rolled back
foreach (var entity in ActiveRecordMediator<Entity>.FindAll())
{
Assert.That(entity, Is.Not.SameAs(savedEntity));
}
}
}
Hier ist mein bester Versuch, die Basisklasse zu erstellen. Sie implementiert korrekt Flush()
so dass der dritte Testfall bestanden wird. Allerdings werden die Transaktionen nicht zurückgesetzt, so dass der zweite Test fehlschlägt.
public class ARTestBase
{
private SessionScope sessionScope;
private TransactionScope transactionScope;
[TestFixtureSetUp]
public void InitialiseAR()
{
ActiveRecordStarter.ResetInitializationFlag();
ActiveRecordStarter.Initialize(typeof (Entity).Assembly, ActiveRecordSectionHandler.Instance);
ActiveRecordStarter.CreateSchema();
}
[SetUp]
public virtual void SetUp()
{
transactionScope = new TransactionScope(OnDispose.Rollback);
sessionScope = new SessionScope();
}
[TearDown]
public virtual void TearDown()
{
sessionScope.Dispose();
transactionScope.Dispose();
}
protected void Flush()
{
sessionScope.Dispose();
sessionScope = new SessionScope();
}
[TestFixtureTearDown]
public virtual void TestFixtureTearDown()
{
SQLiteProvider.ExplicitlyDestroyConnection();
}
}
Beachten Sie, dass ich einen benutzerdefinierten SQLite-Anbieter mit einer In-Memory-Datenbank verwende. Mein benutzerdefinierter Anbieter, der von dieser Blogbeitrag hält die Verbindung ständig offen, um das Schema zu erhalten. Wenn Sie dies entfernen und eine normale SQL Server-Datenbank verwenden, ändert sich das Verhalten nicht.
Gibt es eine Möglichkeit, das gewünschte Verhalten zu erreichen?