2010-12-02 31 views
1

Salutations.Comment faire pour désactiver un paramètre à une méthode stubbed en utilisant Mockito

Je me moque d'un moteur de recherche pour tester dans mon application Web. Ce moteur de recherche renvoie des documents XML avec des schémas différents. Le schéma dépend d'un paramètre appelé ensemble de collecte. Renvoyer des schémas différents basés sur des ensembles de collections est la partie qui est difficile à simuler, car spécifier l'ensemble de collections est fondamentalement une méthode d'installation, et une méthode vide. Ce moteur de recherche est un fichier jar externe, donc je ne peux pas modifier l'API. Je dois travailler avec ce qui a été fourni. Voici un exemple:

Engine engine = factory.getEngine(); 
Search search = engine.getSearch(); 
search.addCollectionSet(someCollectionSet); 
SearchResult result = search.getSearchResult(); 
Document[] documents = result.getAllDocuments(); 

Ensuite, pour chaque document, je peux obtenir le code XML en appelant:

document.getDocumentText(); 

Lorsque j'utilise mes objets fantaisie, getDocumentText() renvoie une chaîne XML, créé par un générateur , qui est conforme au schéma. Ce que je veux faire est d'utiliser un autre type de générateur en fonction de l'ensemble de collection fourni à l'étape 3 dans le premier extrait de code ci-dessus. J'ai essayé de faire quelque chose comme ceci:

doAnswer(new Answer() { 
     Object answer(InvocationOnMock invocation) { 
      if (args == "foo") { 
       SearchResult result = getMockSearchResult(); 
       when(search.getSearchResult()).thenReturn(result); 
      } 
     } 
    }).when(search.addCollectionSet(anyString())); 

Mais cela se traduit par beaucoup de surlignage rouge :)

Au fond, mon objectif est à la clé de addCollectionSet(someCollectionSet) hors de sorte que quand on l'appelle, je peux faire une sorte de désactivation du paramètre et s'assurer qu'un générateur différent est utilisé. Est-ce que quelqu'un sait comment je peux accomplir quelque chose comme ça? Ou y a-t-il peut-être une forme d'Injection de Dépendance qui pourrait être utilisée pour câbler conditionnellement mon générateur?

Merci!

Mise à jour

J'ai changé mon objet usine pour qu'il ne retourne jamais le moteur, mais plutôt, la recherche et trouver des objets de ce moteur, donc maintenant je peux faire quelque chose comme ceci:

Search search = factory.getSearch(collectionSet);

donc ce que je voudrais faire est quelque chose comme ceci:

when(factory.getSearch(anyString()).thenAnswer(new Answer() { 
    Object answer(InvocationOnMock invocation) { 
     switch(args[0]) { 
      case fooSet: return fooSearch; break; 
      case barSet: return barSearch; break; 

En d'autres termes, je veux toujours désactiver la chaîne qui a été transmise à getSearch dans une instruction switch. Certes, je pourrais faire quelque chose de plus comme Felix a suggéré ci-dessous, mais je préférerais avoir tous mes cas enveloppés dans un commutateur. Quelqu'un peut-il donner un exemple de la façon dont cela pourrait être fait? Merci!

Mise à jour

Je l'ai vu que vous pouvez saisir les arguments qui sont passés dans les appels moquaient, mais ces arguments capturés sont utilisés pour les assertions ultérieures. Je n'ai pas vu un moyen que je puisse effacer ces arguments de sorte qu'un appel à mon simulacre renverra des valeurs différentes en fonction des arguments. Il semble qu'il doit y avoir un moyen de le faire, je n'ai tout simplement pas assez d'expérience avec Mockito pour le comprendre. Mais sûrement quelqu'un le fait!

Répondre

1

Je vous recommande d'encapsuler l'appel au code existant dans votre propre objet. Alors vous vous retrouvez avec votre propre méthode le long de ces lignes:

class SearchEngineWrapper { 
    public String getSearchResult(String collection){ 
    Engine engine = factory.getEngine(); 
    Search search = engine.getSearch(); 
    search.addCollectionSet(someCollectionSet); 
    SearchResult result = search.getSearchResult(); 
    ... 
    return document.getDocumentText(); 
    } 
} 

Vous pouvez maintenant se moquer de cette méthode. La méthode documente également bien votre intention. Vous pouvez également tester l'implémentation réelle dans un test d'intégration.

when(searchEngineWrapper.getSearchResult("abc").thenReturn("foo"); 
when(searchEngineWrapper.getSearchResult("xyz").thenReturn("bar"); 
+0

si je devais faire quelque chose comme ça, je voudrais remplacer « foo » avec anyString(), mais faire un commutateur hors de cette chaîne se révèle être difficile. Connaissez-vous un bon moyen de le faire? Si oui, pourriez-vous mettre à jour votre exemple? – Samo

+0

Essayez sans doute de créer deux mocks en interaction est une chose étrange. Cela ne fait pas beaucoup de différence, que vous vous moquiez du code d'un tiers ou de votre emballage autour du code d'un tiers, n'est-ce pas? J'ai également mis à jour l'exemple) –

+0

J'ai trouvé un moyen de faire quelque chose comme vous suggérez ce qui fonctionne le mieux pour nous, mais j'aimerais quand même savoir s'il existe un moyen d'utiliser la méthode anyString() et d'éteindre de la chaîne utilisée. Merci. – Samo