我正在使用 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 数据库不会改变行为。
有没有办法实现所需的行为?