web-dev-qa-db-fra.com

Tests unitaires avec Entity Framework

Je veux tester mes entités construites à l'aide d'Entity Framework. Ma préoccupation est que l'utilisation d'Entity Framework signifie travailler directement avec la source de données. Donc, des idées sur la façon de tester les composants basés sur Entity Framework?

70
Muhammad Soliman

Pour Entity Framework 4, cela semble prometteur: Testabilité et Entity Framework 4.

51
Hans Kesting

Apparemment, c'est très difficile. Éloquemment mis par Erik ici - TDD et ADO.NET Entity Framework

7
gef

Une approche peu coûteuse consiste à configurer un fichier de base de données avec la même structure que votre base de données réelle et à définir la chaîne de connexion dans votre configuration de test unitaire pour pointer vers cela. La base de données n'a pas besoin d'avoir toutes les tables que la vraie possède; juste ceux dont le test unitaire a besoin.

Un inconvénient est que vous devez gérer l'état de la base de données afin que les tests unitaires ne s'influencent pas entre eux ou entre eux pendant et entre les exécutions.

Je sais que cette approche fonctionne lorsque les bases de données de test réel et unitaire utilisent SQL Express, mais je ne connais pas le stubbing dans une base de données SqlExpress pour une base de données SQL complète.

Je me rends compte que ce sont des tests d'intégration technique, mais cela pourrait être moins cher que de refactoriser votre code ou d'apprendre un cadre de simulation.

Exemple de chaîne de connexion réelle:

<add name="DrinksEntities" 
     connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
     ;provider connection string=&quot;Data Source=localhost\sqlexpress;Initial Catalog=Drinks2;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" />

Exemple de chaîne de connexion de test unitaire:

<add name="DrinksEntities" 
     connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
     ;provider connection string=&quot;Data Source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Inventory.mdf;Integrated Security=True;user instance=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" />
6
James McLachlan

Je voudrais partager une autre contribution à cela. J'ai également pu tester des composants et des applications basés sur Entity Framework à l'aide de TypeMock Isolator. Mais c'est commercial.

Jetez un œil à cet article: Présentation du test d'unité Entity Framework avec TypeMock Isolator

4
Muhammad Soliman

Vous allez vouloir utiliser un cadre de simulation pour récupérer des valeurs de simulation plutôt que de frapper les données réelles. Voici une liste de quelques cadres de simulation et des liens vers des captures d'écran pour vous aider à démarrer:

Voici quelques captures d'écran sur la façon de commencer:

4
David P

Étant donné que la version 1 d'Entity Framework rompt quelques grands principes de conception de logiciels, il n'y a vraiment aucun moyen d'appliquer TDD lors de son utilisation dans votre application. Ma recherche pointe vers NHibernate si vous cherchez une solution immédiate. Il a été conçu en pensant aux tests unitaires.

Cependant, si vous pouvez attendre, il semble y avoir de l'espoir pour la prochaine version d'Entity Framework: Procédure pas à pas de développement piloté par les tests avec Entity Framework 4.

4
Jason Stonebraker

Bien que les exemples puissent être très simplistes, j'ai essayé de discuter d'une solution possible à ce problème. Cela implique la séparation des préoccupations et notre cher ami Injection de dépendance.

http://devblog.petrellyn.com/

Contactez-moi si vous souhaitez plus de détails.

3
Jamie Phillips

Je suis d'accord, un cadre moqueur est ce que vous recherchez. Vous créez des objets "simulés" qui ne sont pas récupérés de votre source de données et vous testez les données dans cet objet. Personnellement, j'ai travaillé avec Moq, et j'aime ça - il y a aussi Rhinomocks, ainsi que d'autres.

2
Carl

Après beaucoup de frustration avec cela, j'ai enfin une solution qui me satisfait pour au moins une partie du problème.

Utilisez d'abord une interface de dépôt quelque chose comme:

public interface IRepository
{
    IQueryable<T> GetObjectSet<T>();
}

que nous pouvons utiliser pour renvoyer une collection en mémoire ou une vraie collection sauvegardée par DB. Ensuite, encapsulez vos requêtes dans un objet de requête avec une interface qui ressemble à ceci.

public interface IQuery<T>
{
    IQueryable<T> DoQuery(IQueryable<T> collection);
}

Divisez maintenant vos tests unitaires en 2 groupes. Le premier groupe testera la validité de vos requêtes. faites comme ça:

[TestMethod]
public void TestQueryFoo()
{
     using(var repo = new SqlRepository("bogus connection string"))
     {
         var query = new FooQuery(); // implements IQuery<Foo>
         var result = query.DoQuery(repo.GetObjectSet<Foo>());  // as long as we don't enumerate the IQueryable EF won't notice that the connection string is bogus
         var sqlString = ((System.Data.Objects.ObjectQuery)query).ToTraceString(); // This will throw if the query can't be compiled to SQL
     }
}

Le deuxième ensemble de tests unitaires peut ensuite tester librement votre logique métier sans se soucier de l'étape de compilation SQL qui est, de loin, celle où nous rencontrons le plus de problèmes.

Ce n'est parfait par aucun effort d'imagination, les déclencheurs ne vont évidemment pas être exécutés, les contraintes implémentées par la base de données peuvent être violées et certains problèmes avec le contexte et la base de données se désynchronisant peuvent surgir. Ainsi, même si des tests d'intégration de bout en bout sont encore nécessaires, il est possible de détecter ce qui est le problème le plus courant à l'OMI à résoudre lors de l'exécution dans de simples tests unitaires.

2
Yaur

Voici une agrégation du modèle d'unité de travail + base de données en mémoire + génération de code t4 pour générer automatiquement un faux EF dbContext.

http://mockingcompetence.wordpress.com/2013/05/20/fakingefdatacontext/

il y a quelques problèmes (linq non valide pour les requêtes EF et aucune application FK) avec la réplication exacte d'une vraie connexion EF db pour le moment.

Cependant, avoir un contexte en mémoire pour exécuter rapidement des tests unitaires est presque essentiel pour pouvoir faire TDD ou tout autre type d'approche centrée sur les tests unitaires.

Je publierai des mises à jour du lien ci-dessus au fur et à mesure que je découvrirai plus de problèmes.

0
rickjr82

L'exemple d'application BookLibrary de WPF Application Framework (WAF) Le projet montre comment une application basée sur Entity Framework peut être testée unitaire.

0
jbe

Vous pouvez utiliser une base de données en mémoire pour tester votre modèle Entity Framework. Regardez ici pour plus de détails

0
druss