2010-02-07 6 views
9

J'utilise StructureMap dans un projet Web pour DI IOC. Cela fonctionne parfaitement, mais je n'ai aucune idée de comment écrire des tests unitaires avec StructureMap.Utilisation de StructureMap avec des tests unitaires

dois-je faire cela dans AssemblyInitialize commencer Configuration de StructureMap comme dans global.asax sauf pour datacontext de ne pas utiliser LinqToSqlDataContext en direct, mais certaines données de la mémoire comme celle-ci:

[AssemblyInitialize] 
public static void Start() 
{ 
     ObjectFactory.Configure(x => 
       { 
        x.For<IDataContext>().HttpContextScoped().Use<MemoryDataContext>() 
         .Ctor<string>("connectionString") 
         .Is(ConfigurationManager.ConnectionStrings["DEVConnection"].ConnectionString); 
        x.For<IDepartamentRepository>().Use<DepartamentDB>(); 
        x.For<IDevelopmentProcess>().Use<DevelopmentProcesses>().OnCreation(c => c.User = Current.CurrentUser); 
        x.For<IActivityProcess>().Use<ActivitiesProcess>().OnCreation(c=> c.User = Current.CurrentUser); 
        x.For<IDevDeveloperRepository>().Use<DevDeveloperDB>(); 
        x.For<IDevelopmentRepository>().Use<DevelopmentDB>(); 
        x.For<IActivityRepository>().Use<ActivityDB>(); 
        x.For<IActivityTypeRepository>().Use<ActivityTypeDB>(); 
        x.For<IDevUserRepository>().Use<DevUsersDB>(); 
        x.For<IAttachmentRepository>().Use<AttachmentDB>(); 
       } 
      ); 
} 

puis utiliser des tests ObjectFactory.GetInstance() ou comment je fais ça?

Répondre

21

Vous ne devriez pas avoir besoin de use a DI Container in unit tests du tout. Un conteneur est quelque chose que vous utilisez pour câbler des composants ensemble, mais un test unitaire est un test de chaque composant dans l'isolement.

+0

Je suis d'accord avec ça, mais si j'ai une classe qui consomme plusieurs instances, tout ce que je voudrais échange en utilisant DI est dit DAL à utiliser dans le référentiel de mémoire. Si mon constructeur prend 10 interfaces alors je dois fournir 10 instances manuellement en utilisant DI, le tout fait automatiquement. Même si je devais créer une composition de 10 interfaces en une, j'ai encore besoin de me moquer d'une certaine manière ... –

+0

@PawelCioch Si votre constructeur prend dix dépendances, c'est [probablement en faire trop] (http://stackoverflow.com/a/2420245/126014). Non seulement c'est une odeur de design, mais il est également probable qu'il sera difficile à tester, ou du moins à maintenir les tests. –

+0

Je suppose que je dois changer le travail pour travailler avec des projets plus simples :). La classe qui prend tous ces derniers est le service final pour l'application de console qui a besoin de toutes sortes de référentiels et de filtres. Probablement pourrait re-factoriser mais les algorithmes sont tellement interconnectés qu'il est difficile d'isoler l'unité de travail. En tout cas merci pour vos commentaires. –

5

Je suis d'accord avec Mark. La testabilité est l'une des principales raisons pour lesquelles vous utilisez probablement un conteneur en premier lieu.

Il est parfois utile de créer un test d'intégration pour la configuration de votre conteneur. Par exemple, si vous avez un comportement dans la configuration de votre conteneur, vous voudrez créer des tests pour ce comportement. Dans la configuration de votre conteneur, vous définissez la chaîne de connexion IDataContext via le gestionnaire de configuration.

Le code suivant est similaire à ce que je fais pour tester une telle configuration. Remarquez que j'éviter ObjectFactory (statiques objets singleton ont leurs propres problèmes) et envelopper mon installation de conteneurs dans une classe d'aide bootstrapper:

[Test] 
public void connection_string_should_come_from_application_configuration() 
{ 
    var container = new ContainerBootstraper().Container; 

    var connectionString = container.GetInstance<IDataContext>().ConnectionString 

    connectionString.ShouldEqual("test project application configuration connection string"); 
} 
+0

Serait-ce une mauvaise idée de pointer la comparaison 'ShouldEqual' directement à la valeur AppSettings en question dans ce cas? Je ne prétendrai pas avoir la moindre idée des meilleures pratiques en matière de tests unitaires, mais en lisant ces lignes, je continuais à penser que cela ne semblait pas confirmer que cela venait de la configuration. – patridge

+0

Désolé, mon exemple était très laconique. Je supposais que la configuration du test aurait donné le contexte nécessaire. L'installation serait responsable de s'assurer que le réglage de l'application était présent. – KevM

+0

Est-il possible de poster un échantillon de ce que vous faites avec cette classe Bootstrapper? Je suis confronté à certains des mêmes défis, et je ne suis pas assez brillant pour rassembler cela. –

Questions connexes