2009-12-10 4 views
4

J'espère que quelqu'un pourra m'aider à soulager ma frustration. J'essaie de trouver un bon moyen de tester mes classes d'implémentation de service WCF, mais chaque ressource que j'ai trouvé fournissant une solution est limitée aux services avec une seule méthode/opération.Unité testant un service WCF avec plusieurs dépendances

Dans mon cas, j'ai une classe de service qui contient plusieurs méthodes/opérations de service. Le but de la classe de service est de fournir l'interface au comportement qui est implémenté dans l'application principale. En tant que tel, chaque méthode/opération est chargé de:

  1. accepter un objet d'appel de l'appelant
  2. validation des propriétés de l'objet
  3. créer une instance de la objet de commande applicable que effectue l'opération
  4. mappage des propriétés de l'objet Request à l'objet Command.
  5. exécuter l'objet Command
  6. cartographie des résultats à une réponse objet
  7. retourner la réponse à l'appelant

En outre, la méthode de service gère toutes les exceptions qui se produisent et renvoient une erreur WCF. Nous utilisons Spring.NET pour IoC (DI) et AOP. La classe de service est instanciée par Spring, ce qui nous permet d'utiliser l'aspect ParameterValidation de Spring pour effectuer l'étape 2. Par défaut, nous utilisons également Spring pour l'étape 3.

Pour la plupart, tout cela fonctionne très bien. Cependant, quand vient le temps d'écrire des tests unitaires pour vérifier le comportement d'une méthode de service, je m'embourbe en essayant de trouver la bonne façon de gérer les dépendances du service sur plusieurs objets Command (un par méthode). Soyons clairs, je n'ai pas de problème pour se moquer des objets Command (nous utilisons Moq, btw) et je n'ai pas non plus de problème à faire des tests en boîte noire. J'essaye de faire le test de boîte blanche sur la logique interne, telle que vérifier que l'étape 4 est exécutée correctement ou si l'objet de commande lève une exception, le service la gère correctement. Pour cela, j'utilise des exemples fictifs de l'objet Command.

Le problème consiste à trouver la meilleure pratique pour un scénario où l'objet testé a plusieurs dépendances - en particulier lorsque je ne m'intéresse qu'à l'un d'entre eux pour le test que je cours. L'approche Constructor de DI n'est tout simplement pas pratique car j'aurais besoin d'avoir autant d'arguments pour le constructeur que de méthodes sur mon service (et cela pourrait être beaucoup). L'injection de Setter me préoccupe parce que les setters n'existeraient que pour les tests - et, encore une fois, il y en aurait un grand nombre dans beaucoup de cas.

Le service est conçu pour déléguer l'étape 4 à une méthode virtuelle qui, par défaut, utilise Spring pour instancier l'objet Command mais van être remplacé pour retourner le mock en utilisant l'approche inherit-and-override. Mais cela s'est également avéré trop compliqué.Donc, après avoir parcouru article après article en ligne qui démontrent diverses solutions mais, comme je l'ai dit, ne reflètent jamais qu'un service avec une méthode/opération, je cherche des conseils pour une approche qui sera facile à mettre en œuvre, maintenir et étendre lorsque vous traitez avec des services réels qui contiennent plusieurs méthodes et plusieurs dépendances. Gardez à l'esprit que je ne peux pas utiliser Spring pour injecter des objets Command moqués parce que j'ai besoin de références aux mock afin de les configurer et de vérifier le comportement de la méthode. (Pour ne pas mentionner que mes tests dépendent alors du bon fonctionnement de Spring aussi.)

+0

Lors de mon dernier concert, nous avons trouvé un moyen d'injecter un simulacre dans un service auto-hébergé. Le "test unitaire" (plus d'un test d'acceptation à ce stade) a appelé un client léger qui a appelé le service testé. Si cela convient à vos besoins, je verrai si je peux trouver le code et poster. –

+0

Semble plus comme un test fonctionnel que ce que nous recherchons. En fait, j'aurais dû indiquer plus clairement que j'essaie de tester la mise en œuvre de la classe de service en tant qu '«unité». Je n'utilise même pas la WCF à ce stade. – SonOfPirate

Répondre

0

On dirait que vous avez déjà fait la plupart des durs travaux. Comme vous utilisez déjà un conteneur DI, vous pouvez simplement créer et injecter des Mocks qui intercepteront l'étape 3. Vous pouvez alors recevoir ce qui est reçu par le conteneur DI et comment se comporte la validation pour tester les deux premières étapes alors vous pourriez avoir le Mock retourne tout ce que vous voulez tester les étapes restantes. Vous avez déjà pris une grande dépendance à l'égard de spring.net et vous avez pris cette distance supplémentaire pour injecter vos mocks et les tests de force pour les utiliser me semblent raisonnables. Il doit y avoir un moyen de modifier votre config temporairement pour utiliser un Mock spécifique. Si ce n'est pas le cas, considérez une simple usine à utiliser par votre service pour vous permettre de mettre en place vos Mocks.

+0

Je me rends compte que je viens juste de réitérer votre dernier paragraphe, mais si spring.net entrave les tests, alors contournez-le. – smaclell

1

J'ai généralement mes classes de service ne sont que des façades minces à la fonctionnalité réelle. Dans ce cas, vous pouvez envisager de ne plus tester le service lui-même, mais de déléguer tous les appels à l'un de plusieurs objets internes, ce qui serait individuellement plus testable car ils seraient plus spécifiques.

+0

C'est essentiellement ce que nous faisons, mais je veux quand même vérifier que la délégation fonctionne correctement. Par exemple, si je change une propriété sur mon objet interne (celui auquel je délègue), alors peut-être que cet objet fonctionne correctement mais que je ne mapperai plus correctement l'objet Request dans ma méthode de service. – SonOfPirate

Questions connexes