2009-08-04 7 views
2

Ce qui suit est quelques informations de base sur ce post. Vous pouvez simplement passer à la question si vous le souhaitez:Tests unitaires SQLite NHibernate a généré des relations en cascade

Dans cet excellent article (http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx) l'auteur affirme que « Lors de l'utilisation de NHibernate nous voulons généralement tester seulement trois choses:
1) que les propriétés sont conservées,
2) que la cascade fonctionne comme prévu 3) que les requêtes renvoient le résultat correct -.) que la cartographie est complète & correcte (implicite)

Mon point de vue est qu'il continue à dire que SQLite peut et doit être l'unité outil de test de choix pour faire tout ce qui précède.Il convient de noter que l'auteur semble être l'un des plus expe Les développeurs de NHib expérimentés et expérimentés là-bas, et bien qu'il ne le dise pas expressément dans l'article, il laisse entendre plus tard dans une question que le domaine peut et devrait traiter certaines des lacunes de SQLite.

QUESTION:

Comment utilisez-vous SQLite pour tester les relations en cascade, en particulier étant donné qu'il ne vérifie pas la clé étrangère. Comment tester votre modèle pour vous assurer que les contraintes de clé étrangère ne seront pas un problème de base de données.

Voici quelques tests que j'ai conçus pour tester le comportement en cascade. Le modèle est simplement un département qui peut avoir zéro à plusieurs membres du personnel, avec une cascade définie sur AUCUN.

[Test] 
    public void CascadeSaveIsNone_NewDepartmentWithFetchedStaff_CanSaveDepartment() 
    { 
     _newDept.AddStaff(_fetchedStaff); 
     Assert.That(_newDept.IsTransient(), Is.True); 

     _reposDept.SaveOrUpdate(_newDept); 
     _reposDept.DbContext.CommitChanges(); 

     Assert.That(_newDept.IsTransient(), Is.False); 
    } 

    [Test] 
    public void CascadeSaveIsNone_NewDepartmentWithFetchedStaff_CannotSaveNewStaff() 
    { 
     _newDept.AddStaff(_newStaff); 
     Assert.That(_newDept.IsTransient(), Is.True); 
     Assert.That(_newStaff.IsTransient(), Is.True); 

     _reposDept.SaveOrUpdate(_newDept); 
     _reposDept.DbContext.CommitChanges(); 

     Assert.That(_newDept.IsTransient(), Is.False); 
     Assert.That(_newStaff.IsTransient(), Is.True); 
    } 

    [Test] 
    public void CascadeDeleteIsNone_FetchedDepartmentWithFetchedStaff_Error() 
    { 
     _fetchedDept.AddStaff(_fetchedStaff); 
     _reposDept.SaveOrUpdate(_fetchedDept); 
     _reposStaff.DbContext.CommitChanges(); 

     _reposDept.Delete(_fetchedDept); 
     var ex = Assert.Throws<GenericADOException>(() => _reposDept.DbContext.CommitChanges()); 

     Console.WriteLine(ex.Message); 
     Assert.That(ex.Message, Text.Contains("could not delete:")); 
     Console.WriteLine(ex.InnerException.Message); 
     Assert.That(ex.InnerException.Message, Text.Contains("The DELETE statement conflicted with the REFERENCE constraint")); 
    } 

    [Test] 
    public void Nullable_NewDepartmentWithNoStaff_CanSaveDepartment() 
    { 
     Assert.That(_newDept.Staff.Count(), Is.EqualTo(0)); 

     var fetched = _reposDept.SaveOrUpdate(_newDept); 
     Assert.That(fetched.IsTransient(), Is.EqualTo(false)); 
     Assert.That(fetched.Staff.Count(), Is.EqualTo(0)); 
    } 

Le troisième test, ".._ FetchedDepartmentWithFetchedStaff_Error" fonctionne contre Sql Server, mais pas SQLite puisque celui-ci ne vérifie pas la clé étrangère.

Voici des tests pour l'autre côté de la relation; un membre du personnel peut avoir un département, avec cascade défini sur AUCUN.

[Test] 
    public void CascadeSaveIsNone_NewStaffWithFetchedDepartment_CanSaveStaff() 
    { 
     _newStaff.Department = _fetchedDept; 
     _reposStaff.SaveOrUpdate(_newStaff); 
     _reposStaff.DbContext.CommitChanges(); 

     Assert.That(_newStaff.Id, Is.GreaterThan(0)); 
    } 

    [Test] 
    public void CascadeSaveIsNone_NewStaffWithNewDepartment_Error() 
    { 
     _newStaff.Department = _newDept; 
     Assert.That(_newStaff.IsTransient(), Is.True); 

     var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff)); 
     Console.WriteLine(ex.Message); 
     Assert.That(ex.Message, Text.Contains("not-null property references a null or transient value")); 
    } 

    [Test] 
    public void CascadeDeleteIsNone_FetchedStaffWithFetchedDepartment_DeletesTheStaff_DoesNotDeleteTheDepartment() 
    { 
     _newStaff.Department = _fetchedDept; 
     _reposStaff.SaveOrUpdate(_newStaff); 
     _reposStaff.DbContext.CommitChanges(); 

     _reposStaff.Delete(_newStaff); 
     Assert.That(_reposStaff.Get(_newStaff.Id), Is.Null); 
     Assert.That(_reposDept.Get(_fetchedDept.Id), Is.EqualTo(_fetchedDept)); 
    } 

    [Test] 
    public void NotNullable_NewStaffWithUnknownDepartment_Error() 
    { 
     var noDept = new Department("no department"); 
     _newStaff.Department = noDept; 

     var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff)); 
     Console.WriteLine(ex.Message); 
     Assert.That(ex.Message, Text.Contains("not-null property references a null or transient")); 
    } 

    [Test] 
    public void NotNullable_NewStaffWithNullDepartment_Error() 
    { 
     var noDept = new Department("no department"); 
     _newStaff.Department = noDept; 

     var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff)); 
     Console.WriteLine(ex.Message); 
     Assert.That(ex.Message, Text.Contains("not-null property references a null or transient")); 
    } 

Ces tests ont abouti contre Sql Server et SQLite. Puis-je faire confiance aux tests SQLite? Est-ce que ces tests valables?

Cheers,
Berryl

Répondre

3

Si je comprends bien l'article, il est de tester la cartographie NHibernate. À mon avis, cela n'a rien à voir avec les problèmes liés à la base de données mais avec le test des attributs nhibernate que vous définissez dans votre mapping. Il n'est pas nécessaire d'affirmer qu'il n'est pas possible de créer des données invalides: il suffit de prouver que votre code crée le résultat souhaité et/ou qu'il vérifie les éléments que vous voulez vérifier. Vous pouvez tester cascade, cascade-delete et delete-orphelin. tout ce que vous voulez comme vous le faites dans les tests de travail avec sqlite. Mais le troisième test tente de tester la contrainte, ce qui ne dérange pas les nhibernates.

Si vous voulez tester vos contraintes Db, vous devez utiliser votre db de production et non sqlite. Vous pouvez le faire avec ou sans hibernation mais cela n'a rien à voir avec votre mapping. Si, d'un autre côté, vous voulez vraiment une solution de travail pour vos tests de clé étrangère avec SQLite, vous pouvez essayer d'utiliser ce foreign_key_trigger_generator. Je n'ai pas essayé mais il semble générer des triggers avant-insert qui assurent l'existence du Pk référencé. Peut-être que vous pourriez écrire un commentaire quand cet outil est utile.