2010-09-15 3 views
6

Est-il possible d'obtenir WSDL.exe pour générer des interfaces ainsi que, ou à la place de, des classes concrètes lorsqu'il génère des proxys vers un service Web?WSDL.exe - Génère une interface aussi bien qu'une classe concrète pour simuler/simuler facilement plus tard

Nous consommons un service Web tiers à partir d'une application ASP.Net et avons généré nos classes proxy à l'aide de WSDL.exe tout à fait bien.

Je veux maintenant écrire des tests sur mon wrapper et mes classes business en simulant le service web. Il n'y a pas d'interface ou de classe de base abstraite pour le proxy, et ils sont marqués en interne, ce qui signifie que je ne peux pas en hériter sans mettre mon code de test Faux/faux dans mon projet/mes assemblées.

Je pourrais créer manuellement une interface (en utilisant resharper) et éditer la classe, cependant si la 3ème partie change leur service WSDL/Web, mes successeurs devront également éditer manuellement l'interface, et générer automatiquement des classes, qui jamais Cela semble être une bonne idée.

Quelle est la manière la plus élégante de faire semblant ou de se moquer de ce service? Devrais-je mettre le faux dans le projet d'entreprise? Dois-je modifier manuellement les fichiers et créer une interface? Dois-je faire quelque chose de complètement différent?

+0

Notez que WCF n'a pas ce problème. –

Répondre

6

La réponse de Philip Je suis parti sur un, et peut avoir trouvé une solution de travail. En utilisant WSDL.exe, j'ai généré les interfaces (en utilisant le commutateur/si) et classes de proxy normales, et ajouté à la fois à mon projet d'entreprise. J'ai ensuite créé une nouvelle classe qui hérite de la classe concrète ET implémente l'interface. Cette petite classe ne contenait pratiquement pas de code, car les membres concrets hérités fournissaient une implémentation implicite des membres de l'interface. Le code a été compilé pour la première fois et j'ai pu substituer cette petite classe "shim" (? Adapter?) À mes tests d'intégration, et exécuter des appels sur le serveur tiers en direct.

Je peux maintenant créer d'autres classes (simulacres ou fausses) qui implémentent l'interface, et les substituer à la place de la classe "shim". OK, j'ai travaillé un peu plus loin, et à moins de complications, ça marche.

Le premier problème important est que les classes proxy sont toujours marquées "internal", donc la classe dérivée (adapter/shim) doit également être interne.Ce n'est pas un problème si vous insérez une classe Factory dans votre projet/assemblage d'entreprise, ce qui augmente les classes proxy et les renvoie en tant qu'interface.

Le deuxième problème que j'ai constaté était que nous définissions explicitement les propriétés URL et timeout de la Webserice, mais celles-ci ne sont pas incluses dans l'interface mais héritées de System.Web.Services.Protocols.WebClientProtocol via SoapHttpClientProtocol. Encore une fois, j'ai traité cela en usine, car c'est un détail de mise en œuvre que je suis heureux n'est pas dans l'interface.

Editer: Cela fonctionne encore très bien pour moi tout en testant et en développant notre façade. Depuis que j'ai obtenu le proxy derrière une interface, j'ai également créé une classe de décorateur de journalisation, qui capture des exemples d'appels d'exemples pour le débogage et lorsque le serveur tiers est hors ligne.

J'ai rédigé ce que je l'ai fait dans un peu plus en détail ici: http://www.flowerchild.org.uk/archive/2010/09/21/mocking-or-faking-or-maybe-stubbing-a-wsdl-exe-soap.html

+0

+1 Cette réponse est géniale. J'ai fait la même chose que vous décrivez, mais j'ai eu le problème que je devais éditer le code de proxy généré. Parce qu'il inclut des types qui sont également définis dans l'interface. Comment avez-vous réussi à éviter cela? – GarethOwen

+1

Le lien est rompu. Nouveau lien: http://www.flowerchild.org.uk/archive/2010/09/21/mocking-or-faking-or-maybe-stubbing-a-wsdl-exe-soap.html – Bobson

+0

Merci @Bobson - lien actualisé. Bien que je profite de l'occasion pour attirer l'attention de tous ceux qui lisent, cela remonte à plusieurs années et ne représente probablement pas la meilleure pratique aujourd'hui. –

3

Vous pouvez exécuter wsdl avec le commutateur /serverinterface ou /si pour obtenir des interfaces pour chaque liaison dans le fichier wsdl. Ceci est destiné à vous donner le squelette côté serveur à partir d'un document wsdl, mais les interfaces devraient vous mettre sur votre chemin - si je comprends bien la question. - Après avoir lu le commentaire, je crois que j'ai mal compris la question - vous voulez une interface client/concrète afin que vous puissiez coder pour ne pas implémenter le contrat. Le commutateur /si ne vous donnera probablement pas ce que vous voulez du tout. Je ne suis pas au courant d'un commutateur qui peut vous donner ce comportement, car wsdl crée essentiellement l'une des trois choses suivantes: 1) classes proxy client: 2) classes abstraites serveur (pour créer une implémentation serveur) 3) interfaces serveur (encore une fois, pour créer une implémentation serveur - c'est juste iface au lieu de la classe abstraite) Je ne vois aucun moyen de forcer les classes proxy client à implémenter des interfaces (autres que INotifyPropertyChanged sur les types de données)

+0

Merci Philippe, Est-ce qu'il génère aussi les classes proxy, implémentant cette interface? Edit: C'est-à-dire, je veux seulement écrire mon faux, j'ai encore besoin des vraies classes de proxy aussi. –

+0

Je viens de l'essayer, avec le flag/si, et je n'ai que l'interface, pas d'implémentation. Je vais continuer à enquêter si. –

+0

Voir mes modifications - Je crains que vous ne deviez écrire un outil de transformation post-wsdl, ou trouver une autre approche pour faire ce que vous voulez. –

1

J'ai toujours trouvé que ces classes générées sont trop grosses pour se moquer facilement (trop de méthodes/propriété). Créez plutôt une façade ou un référentiel qui implémente uniquement les appels dont vous avez besoin, et repasse les objets de style DTO avec les propriétés qui vous intéressent.

Ecrivez des tests d'intégration simples sur le Webservice réel, puis simulez Facade plus simple dans le reste des tests.

Un avantage supplémentaire de cette approche est que vous obtenez effectivement une couche anticorruption, donc les modifications apportées à la 3ème partie n'affecteront qu'une petite partie de votre code.

+0

Salut David, Bon point, mais c'est la façade que j'essaie de tester. Le service que nous consommons est la cause, il utilise beaucoup de XML embarqué, la façade utilise des objets, mais je dois m'assurer que les appels que le Facade effectue vers le service sont sérialisés en XML qui valide par rapport aux schémas fournis. le service. Alors que le proxy et les interfaces sont un peu énormes, je peux laisser les stubbs VS/Resharper en place pour toutes les méthodes, à l'exception des méthodes intéressantes, donc ce n'est pas trop de travail. peut-être que notre façade n'est pas vraiment une façade parce qu'elle contient une logique de traduction. –

Questions connexes