背景:
我的团队致力于确保直接从结帐,我们的代码编译和单元测试成功运行。为了促进这一点并测试我们的一些 NHibernate 映射,我们在存储库中添加了一个 SQLite DB,它是我们生产 SQL Server 2005 数据库的镜像。我们使用的是最新版本:MbUnit3(Gallio 的一部分)、System.Data.SQLite 和 NHibernate。
问题:
我发现以下单元测试不适用于 SQLite,尽管对 SQL Server 2005 执行没有问题。
[Test]
[Rollback]
public void CompleteCanPersistNode()
{
// returns a Configuration for either SQLite or SQL Server 2005 depending on how the project is configured.
Configuration config = GetDbConfig();
ISessionFactory sessionFactory = config.BuildSessionFactory();
ISession session = sessionFactory.OpenSession();
Node node = new Node();
node.Name = "Test Node";
node.PhysicalNodeType = session.Get<NodeType>(1);
// SQLite fails with the exception below after the next line called.
node.NodeLocation = session.Get<NodeLocation>(2);
session.Save(node);
session.Flush();
Assert.AreNotEqual(-1, node.NodeID);
Assert.IsNotNull(session.Get<Node>(node.NodeID));
}
我得到的异常(仅在使用 SQLite 时)如下:
NHibernate.ADOException:无法打开连接---> System.Data.SQLite.SQLiteException: 数据库文件被锁定 数据库被锁定 在 System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 在 System.Data.SQLite.SQLiteDataReader.NextResult() 在 System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd,CommandBehavior 行为) 在 System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() 在 System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection 连接,布尔 deferredLock) 在 System.Data.SQLite.SQLiteConnection.BeginDbTransaction(IsolationLevel 隔离级别) 在 System.Data.SQLite.SQLiteConnection.BeginTransaction() 在 System.Data.SQLite.SQLiteEnlistment..ctor(SQLiteConnection cnn,事务范围) 在 System.Data.SQLite.SQLiteConnection.EnlistTransaction(事务事务) 在 System.Data.SQLite.SQLiteConnection.Open() 在 NHibernate.Connection.DriverConnectionProvider.GetConnection() 在 NHibernate.Impl.SessionFactoryImpl.OpenConnection() --- 内部异常堆栈跟踪结束 --- 在 NHibernate.Impl.SessionFactoryImpl.OpenConnection() 在 NHibernate.AdoNet.ConnectionManager.GetConnection() 在 NHibernate.AdoNet.AbstractBatcher.Prepare(IDbCommand cmd) 在 NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd) 在 NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session) 在 NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 在 NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor 会话,QueryParameters 查询参数,布尔 returnProxies) 在 NHibernate.Loader.Loader.LoadEntity(ISessionImplementor 会话,对象 id,IType 标识符类型,对象 optionalObject,字符串 optionalEntityName,对象 optionalIdentifier,IEntityPersister 持久化) 在 NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor 会话,对象 id,对象 optionalObject,对象 optionalId) 在 NHibernate.Loader.Entity.AbstractEntityLoader.Load(对象 id,对象 optionalObject,ISessionImplementor 会话) 在 NHibernate.Persister.Entity.AbstractEntityPersister.Load(对象 id,对象 optionalObject,LockMode lockMode,ISessionImplementor 会话) 在 NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent 事件,IEntityPersister 持久化,EntityKey keyToLoad,LoadType 选项) 在 NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent 事件,IEntityPersister 持久化,EntityKey keyToLoad,LoadType 选项) 在 NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent 事件,IEntityPersister 持久化,EntityKey keyToLoad,LoadType 选项) 在 NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent 事件,IEntityPersister 持久化,EntityKey keyToLoad,LoadType 选项) 在 NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent 事件,LoadType loadType) 在 NHibernate.Impl.SessionImpl.FireLoad(LoadEvent 事件,LoadType loadType) 在 NHibernate.Impl.SessionImpl.Get(字符串 entityName,对象 id) 在 NHibernate.Impl.SessionImpl.Get(类型 entityClass,对象 id) 在 NHibernate.Impl.SessionImpl.Get[T](对象 id) D:\dev\598\Code\test\unit\DataAccess.Test\NHibernatePersistenceTests.cs
当使用 SQLite 并且未指定 [Rollback] 属性时,测试也成功完成。
问题:
这是 MbUnit3 用于 [Rollback] 的 System.Data.SQLite 的 TransactionScope 实现的问题还是 SQLite 引擎的限制?
有没有办法编写这个单元测试,针对 SQLite,回滚以避免每次运行测试时影响数据库?