Utilisation de années MbUnit3 [Rollback] pour les tests unitaires interactions NHibernate avec SQLite

StackOverflow https://stackoverflow.com/questions/691151

Question

Contexte:

Mon équipe se consacre à assurer que notre code compile et tests unitaires exécuté avec succès directement à partir de la caisse. Pour faciliter cela et tester certains de nos applications NHibernate, nous avons ajouté une SQLite DB à notre référentiel qui est un miroir de notre base de données SQL Server 2005 la production. Nous utilisons les dernières versions de:. MbUnit3 (partie de Gallio), System.Data.SQLite et NHibernate

Problème:

J'ai découvert que le test unitaire suivant ne fonctionne pas avec SQLite, en dépit de l'exécution sans problème contre 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));
    }

L'exception que je reçois (seulement lorsque vous travaillez avec SQLite) suit:

NHibernate.ADOException: cannot open connection --->
System.Data.SQLite.SQLiteException:
  The database file is locked database is locked
    at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
    at System.Data.SQLite.SQLiteDataReader.NextResult()
    at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
    at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
    at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
    at System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection connection, Boolean deferredLock)
    at System.Data.SQLite.SQLiteConnection.BeginDbTransaction(IsolationLevel isolationLevel)
    at System.Data.SQLite.SQLiteConnection.BeginTransaction()
    at System.Data.SQLite.SQLiteEnlistment..ctor(SQLiteConnection cnn, Transaction scope)
    at System.Data.SQLite.SQLiteConnection.EnlistTransaction(Transaction transaction)
    at System.Data.SQLite.SQLiteConnection.Open()
    at NHibernate.Connection.DriverConnectionProvider.GetConnection()
    at NHibernate.Impl.SessionFactoryImpl.OpenConnection()
    --- End of inner exception stack trace ---
    at NHibernate.Impl.SessionFactoryImpl.OpenConnection()
    at NHibernate.AdoNet.ConnectionManager.GetConnection()
    at NHibernate.AdoNet.AbstractBatcher.Prepare(IDbCommand cmd)
    at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)
    at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session)
    at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
    at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
    at NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister)
    at NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId)
    at NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session)
    at NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session)
    at NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
    at NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
    at NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
    at NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
    at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType)
    at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType)
    at NHibernate.Impl.SessionImpl.Get(String entityName, Object id)
    at NHibernate.Impl.SessionImpl.Get(Type entityClass, Object id)
    at NHibernate.Impl.SessionImpl.Get[T](Object id)
D:\dev\598\Code\test\unit\DataAccess.Test\NHibernatePersistenceTests.cs

Lorsque SQLite est utilisé et le [Rollback] attribut est pas spécifié, le test se termine également avec succès.

Question:

Est-ce un problème avec la mise en œuvre de System.Data.SQLite de TransactionScope qui utilise MbUnit3 pour [Rollback] ou une limitation du moteur SQLite?

Est-il possible d'écrire ce test unitaire, travaillant contre SQLite, qui rollback de manière à éviter d'affecter la base de données chaque fois que le test est exécuté?

Était-ce utile?

La solution

Vérifiez si vous connection.release_mode=on_close ne pas manquer dans votre configuration SQLite NHibernate. ( documents de référence )

BTW: toujours disposer de votre ISession et ISessionFactory

.

Autres conseils

Ce n'est pas une vraie réponse à vous poser des questions, mais probablement une solution pour résoudre le problème.

J'utilise une implémentation de SQL Lite en mémoire pour mes tests d'intégration. Je construis le schéma et remplir la base de données avant chaque test. La création de schéma et le remplissage des données initiales arrive très rapide (moins de 0,01 secondes par test) car il est une base de données en mémoire.

Pourquoi utilisez-vous une base de données physique?

Edit: réponse à répondre au sujet de la question ci-dessus:

1.) Parce que je migré mon schéma et les données directement à partir de SQL Server 2005 et je veux persister dans le contrôle source.

  • Je recommande de stocker un fichier avec le schéma de base de données et un fichier ou d'un script qui crée les données de l'échantillon dans le contrôle source. Vous pouvez générer le fichier à l'aide express de gestion de studion serveur SQL, vous pouvez le générer à partir de vos applications NHibernate ou vous pouvez utiliser un outil comme sql comparer et vous pouvez probablement trouver d'autres solutions pour cela quand vous en avez besoin. Les fichiers texte sont stockés plus facile dans les systèmes de contrôle de version, puis compléter les fichiers de base de données binaires.

2.) Est-ce que quelque chose au sujet du différent moteur SQLite en mémoire de telle sorte qu'il résoudrait cette difficulté?

  • Il peut résoudre vos problèmes parce que vous pouvez recréer votre base de données avant chaque test. Votre base de données en cours de test sera en l'état que vous attendez qu'il soit avant chaque test est exécuté. Un avantage de cela est qu'il n'y a pas besoin de rouler les transactions en cours, mais je l'ai test similaire avec courir dans SqlLite mémoire et il a travaillé comme aspecté.

Ditch [Rollback] et utilisez NDbUnit . Je l'utilise moi-même pour ce scénario exact et il travaille beaucoup.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top