Я использую Castle ActiveRecord для персистентности и пытаюсь написать базовый класс для моих тестов персистентности, который будет выполнять следующее:
- Откройте транзакцию для каждого тестового примера и откатите ее в конце тестового примера, чтобы я получил чистую базу данных для каждого тестового примера, при этом мне не нужно перестраивать схему для каждого тестового примера.
- Предоставьте возможность сбрасывать мой сеанс NHibernate и получать новый в середине теста, чтобы я знал, что мои персистентные операции действительно попали в БД, а не только в сеанс NHibernate.
Чтобы доказать, что мой базовый класс (ARTestBase
) работает, я предложил следующие примеры тестов.
[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));
}
}
}
Вот мои лучшие усилия в базовом классе. Он правильно реализует Flush()
, поэтому третий тестовый пример проходит. Однако он не выполняет откат транзакций, поэтому второй тест не пройден.
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();
}
}
Обратите внимание, что я использую пользовательский поставщик SQLite с базой данных в памяти. Мой пользовательский провайдер, взятый из этого сообщения в блоге , всегда поддерживает соединение открытым для поддержки схемы. Удаление этого и использование обычной базы данных SQL Server не изменяет поведение.
Есть ли способ добиться необходимого поведения?