2010-11-04 17 views
1

J'ai du code qui effectue une opération de base de données héritée, puis traite le résultat. Je veux écrire un test unitaire qui vérifie la méthode qui appelle le code existant sans interagir avec la 'base de données'.Comment puis-je supprimer les dépendances au code d'un tiers lors du test unitaire?

Mon code ressemble à ceci:

public static bool CallRoutine(LegacySession session, /* routine params*/) 
    { 
     try 
     { 
      LegacyRoutine routine = session.CreateRoutine(/* routine params */); 

      routine.Call(); 

      // Process result 

     } 
     catch (LegacyException ex) 
     { 
      // Perform error handling 
     } 
    } 

Si cela était tout mon code, je créerais des interfaces que le LegacySession et LegacyRoutine implémentent puis écrire des tests unitaires qui utilisent des implémentations simulacres de ces interfaces en utilisant MOQ ou quelque chose similaire. Le problème est que je n'ai pas accès au code pour LegacyRoutine ou LegacySession donc je ne peux pas les faire implémenter une interface.

Des idées sur comment je pourrais faire cela sans trop changer le code de production?

+0

Avez-vous regardé dans des bibliothèques moqueuses comme Moq: http://code.google.com/p/moq/ – Kane

+0

@Kane: J'avais l'intention d'utiliser Moq mais je pensais que je devais dériver les classes pour être 'Moqed' à partir d'une interface pour le faire? Je ne peux pas changer l'une ou l'autre des classes Legacy ... –

Répondre

5

Si vous ne pouvez pas accéder à LegacyRoutine (je devine qu'il est dans une DLL de référence), pourquoi ne pas simplement créer une enveloppe pour, puis Flick on/off différentes implémentations:

public interface ILegacyWrapper 
{ 
    ILegacyRoutine CreateRoutine(); 
    // etc etc 
} 

public interface ILegacyRoutine 
{ 
    // put members of LegacyRoutine 
} 

Savoir ce que je veux dire? Juste se moquer de tout dans des enveloppes/interfaces.

Ensuite, vous pouvez aller:

ILegacyRoutine routine = session.CreateRoutine(/* routine params */) 

séance serait déclarée comme ILegacyWrapper, mais mis en œuvre avec un béton maquette.

En outre, il va sans dire (mais je le dis de toute façon), vous devriez envisager un cadre DI pour vous simplifier la vie. Sinon, vous finirez par IFoo foo = new Foo() (injection codée en dur) partout.

StructureMap est mon poison DI de choix.

HTH

+1

Je pense que c'est le chemin à suivre - créer une enveloppe autour de la session, j'espérais qu'il y aurait une supercherie rusée qui permettrait d'éviter la nécessité de créer un nouvel ensemble des classes de wrapper car ce truc est utilisé dans beaucoup d'endroits et ils devront tous être changés manuellement. –

+1

C'est pourquoi vous utilisez l'injection de dépendances. De cette façon, vous avez seulement besoin de changer 1 place (Registre). Faites-moi savoir si vous trouvez une meilleure option, mais c'est la seule façon que je peux voir. – RPM1984

1

Vous pouvez écrire une enveloppe fine sur leur API pour laquelle avait une interface. Que ce soit une chose pratique à faire ou non dépend plutôt de la taille de l'API.

0

Je vous conseille d'utiliser un cadre d'injection de depedency. Il vous aide à faire en sorte que vos classes soient plus librement copiées en séparant les dépendances de classes externes en objets qui sont injectés dans vos classes. Ces objets sont souvent représentés par une interface, ce qui vous aide à utiliser différentes implémentations en production et lors des tests. De cette façon, vous n'aurez pas besoin d'appeler la base de données externe lors des tests. Je peux recommander Ninject. Cela rend l'injection de dépendance beaucoup plus facile que de le faire manuellement.