2009-12-16 5 views
1

Je teste un code qui utilise StructureMap pour l'inversion de contrôle et des problèmes sont survenus lorsque j'utilise différentes classes concrètes pour la même interface.StructureMap n'est pas réinitialisé entre les tests NUnit

Par exemple:

[Test] 
public void Test1() 
{ 
    ObjectFactory.Inject<IFoo>(new TestFoo()); 

    ... 
} 

[Test] 
public void Test2() 
{ 
    ObjectFactory.Initialize(
     x => x.ForRequestedType<IFoo>().TheDefaultIsConcreteType<RealFoo>() 
    ); 
    // ObjectFactory.Inject<IFoo>(new RealFoo()) doesn't work either. 

    ... 
} 

Test2 fonctionne très bien si elle fonctionne par lui-même, en utilisant un RealFoo. Mais si Test1 s'exécute en premier, Test2 finit par utiliser un TestFoo au lieu de RealFoo. Les tests NUnit ne sont-ils pas censés être isolés? Comment réinitialiser StructureMap?

Assez curieusement, Test2 échoue si je n'inclue pas l'expression Initialize. Mais si je l'inclue, il sera ignoré ...

Répondre

2

Si vous devez utiliser ObjectFactory dans vos tests, dans votre SetUp ou TearDown, appelez ObjectFactory.ResetAll().

Encore mieux, essayez de faire passer votre code de dépend de ObjectFactory. Toute classe qui doit extraire des éléments du conteneur (autre que la méthode de démarrage) peut prendre un IContainer, qui sera automatiquement rempli par StructureMap (en supposant que la classe elle-même est extraite du conteneur). Vous pouvez référencer l'IContainer enveloppé par ObjectFactory via sa propriété Container. Vous pouvez également éviter d'utiliser ObjectFactory complètement et créer simplement une instance d'un conteneur que vous gérez vous-même (elle peut être configurée de la même manière que ObjectFactory).

+0

Mon objet ObjectFactory ne possède pas ResetAll() ou une propriété Container ... est-ce nouveau dans 2.5.3? ... Mais quoi qu'il en soit, dites-vous qu'il est préférable d'utiliser l'injection de dépendance avec un IContainer? – parcydarks

+0

Ils sont tous les deux disponibles dans la dernière version du tronc, que j'utilise depuis un moment - je ne suis pas sûr qu'ils aient été dans la dernière version. Et oui, pour les endroits où vous devez faire l'emplacement de service, je pense qu'il est préférable de le faire à partir d'un IContainer injecté, plutôt que d'appeler l'ObjectFactory statique directement. –

0

Bien sûr, il ne se réinitialise pas entre les tests. ObjectFactory est une enveloppe statique autour d'un InstanceManager; il est statique à travers un AppDomain et comme les tests sont exécutés dans le même AppDomain, c'est pourquoi il n'est pas réinitialisé. Vous devez TearDownObjectFactory entre les tests ou configurer un nouveau Container pour chaque test (c'est-à-dire, évitez d'utiliser le ObjectFactory statique). Incidemment, c'est la raison principale pour éviter l'état global et les singletons: ils ne sont pas favorables aux tests.

Depuis le guide Google Writing Testable Code:

mondial Etat: état global est mauvais de théorique, maintenabilité, et le point de vue de la compréhensibilité, mais est supportable au moment de l'exécution aussi longtemps que vous avez une instance de ton application. Cependant, chaque test est une petite instanciation de votre application contrairement à une instance d'application en production. L'état global persiste d'un test à l'autre et crée une confusion de masse. Les tests sont isolés mais pas ensemble. Pire encore, les tests échouent ensemble, mais les problèmes ne peuvent pas être reproduits isolément. L'ordre des essais est important. Les API ne sont pas claires sur l'ordre d'initialisation et l'instanciation d'objet, et ainsi de suite. J'espère que maintenant la plupart des développeurs conviennent que l'état global devrait être traité comme GOTO.

0

Oui, les tests NUnit sont censés être isolé et il est votre responsabilité pour vous assurer qu'ils sont isolés. La solution consiste à réinitialiser ObjectFactory dans la méthode TearDown de votre appareil de test. Vous pouvez utiliser ObjectFactory.EjectAllInstancesOf() par exemple.

+1

Bien, cela a du sens. Mais ObjectFactory.EjectAllInstancesOf () ne semble pas fonctionner, que ce soit dans TearDown ou à droite dans Test2. – parcydarks

Questions connexes