Ce que fait un référentiel, c'est traduire de votre domaine vers votre infrastructure DAL, comme NHibernate ou Doctrine, ou vos classes exécutant SQL. Cela signifie que votre référentiel appellera des méthodes sur ledit framework pour effectuer ses tâches: votre référentiel construit les requêtes nécessaires pour récupérer les données. Si vous n'utilisez pas de cadre ORM (j'espère que vous l'êtes ...), le référentiel serait l'endroit où les instructions SQL brutes sont construites.
La plus fondamentale de ces méthodes est la sauvegarde: dans la plupart des cas, cela passera simplement l'objet du référentiel à l'unité de travail (ou à la session).
public void Save(Car car)
{
session.Save(car);
}
Mais regardons un autre exemple, par exemple aller chercher une voiture par son ID. Cela pourrait ressembler
public function GetCarWithId(String id)
{
return Session.QueryOver<Car>()
.Where(x => x.Id == id)
.SingleOrDefault();
}
Ce n'est pas encore trop complexe, mais vous pouvez imaginer avec de multiples conditions (faites-moi toutes les voitures fabriquées après 2010 pour toutes les marques du groupe 'Volkswagen') cela devient difficile. Donc, en vrai mode TDD, vous devez tester cela. Il y a plusieurs moyens de le faire.
Option 1: se moquer des appels passés au cadre ORM
Bien sûr, vous pouvez vous moquer de l'objet Session et simplement affirmer que les bons appels sont effectués. Bien que cela teste le référentiel, il n'est pas vraiment piloté par les tests car vous testez simplement que le référentiel ressemble en interne à ce que vous voulez. Le test dit essentiellement que "le code devrait ressembler à ceci". C'est quand même une approche valable, mais on a l'impression que ce genre de test a très peu de valeur.
Option 2: (Re) construire la base de données à partir des tests
Certains frameworks DAL vous permettent de créer la structure complète de la base de données sur la base des fichiers de mappage que vous créez pour mapper le domaine sur les tables. Pour ces cadres, le moyen de tester les référentiels consiste souvent à créer la base de données avec une base de données en mémoire lors de la première étape du test et à ajouter des objets à l'aide du cadre DAL à la base de données en mémoire. Après cela, vous pouvez utiliser le référentiel sur la base de données en mémoire pour tester si les méthodes fonctionnent. Ces tests sont plus lents, mais très valables et conduisent vos tests. Cela nécessite une certaine coopération de votre cadre DAL.
Option 3: test sur une base de données réelle
Une autre approche consiste à tester sur une base de données réelle et à isoler les plus instables. Vous pouvez le faire de plusieurs manières: entourez vos tests d'une transaction, nettoyez manuellement (ne recommande pas car très difficile à maintenir), reconstruisez complètement la base de données après chaque étape ... Selon l'application que vous construisez, cela peut ou peut pas faisable. Dans mes applications, je peux complètement créer une base de données de développement local à partir du contrôle de code source et mes tests sur référentiels utilisent des transactions pour isoler complètement les tests les uns des autres (transaction ouverte, insérer des données, référentiel de test, transaction de restauration). Chaque build configure d'abord la base de données de développement locale, puis effectue des tests isolés des transactions pour les référentiels sur cette base de données de développement locale. Il'
Ne testez pas le DAL
Si vous utilisez un framework DAL tel que NHibernate, évitez d'avoir à tester ce framework. Vous pouvez tester vos fichiers de mappage en enregistrant, en récupérant puis en comparant un objet de domaine pour vous assurer que tout va bien (assurez-vous de désactiver toute sorte de mise en cache), mais ce n'est pas aussi requis que de nombreux autres tests que vous devriez écrire. J'ai tendance à le faire principalement pour les collections sur les parents avec des conditions sur les enfants.
Lorsque vous testez le retour de vos référentiels, vous pouvez simplement vérifier si certaines propriétés d'identification sur votre objet de domaine correspondent. Cela peut être un identifiant, mais dans les tests, il est souvent plus avantageux de vérifier une propriété lisible par l'homme. Dans la section «obtenez-moi toutes les voitures fabriquées après 2010 ...», cela pourrait simplement vérifier que cinq voitures sont retournées et que les plaques d'immatriculation sont «insérer la liste ici». L'avantage supplémentaire est qu'il vous oblige à penser au tri ET que votre test force automatiquement le tri. Vous seriez surpris du nombre d'applications triant plusieurs fois (retour trié à partir de la base de données, tri avant de créer un objet de vue, puis tri de l'objet de vue, le tout sur la même propriété au cas où ), ou supposant implicitement le tri du référentiel et suppression accidentelle qui étaient en cours de route, brisant l'interface utilisateur.
«Test unitaire» n'est qu'un nom
À mon avis, les tests unitaires ne devraient généralement pas toucher la base de données. Vous créez une application de sorte que chaque morceau de code qui a besoin de données d'une source le fasse avec un référentiel, et ce référentiel est injecté en tant que dépendance. Cela permet une moquerie facile et toute la bonté TDD que vous voulez. Mais à la fin, vous voulez vous assurer que vos référentiels remplissent leurs fonctions et si la façon la plus simple de le faire est de toucher une base de données, tant pis. J'ai depuis longtemps abandonné l'idée que «les tests unitaires ne devraient pas toucher la base de données» et j'ai appris qu'il y a de très réelles raisons de le faire. Mais seulement si vous pouvez le faire automatiquement et à plusieurs reprises. Et la météo que nous appelons un tel test un «test unitaire» ou un «test d'intégration» est sans objet.