Question

J'implémente un client utilisant un service Web. Je veux réduire les dépendances et décidé de me moquer du webservice.
J'utilise mockito , c'est l'avantage par rapport à EasyMock de pouvoir se moquer des cours, pas juste des interfaces. Mais ce n'est pas la question.

Dans mon test, j'ai ce code:

// Mock the required objects
Document mDocument = mock(Document.class);
Element mRootElement = mock(Element.class);
Element mGeonameElement = mock(Element.class);
Element mLatElement = mock(Element.class);
Element mLonElement = mock(Element.class);

// record their behavior
when(mDocument.getRootElement()).thenReturn(mRootElement);
when(mRootElement.getChild("geoname")).thenReturn(mGeonameElement);
when(mGeonameElement.getChild("lat")).thenReturn(mLatElement);
when(mGeonameElement.getChild("lon")).thenReturn(mLonElement);
// A_LOCATION_BEAN is a simple pojo for lat & lon, don't care about it!
when(mLatElement.getText()).thenReturn(
    Float.toString(A_LOCATION_BEAN.getLat()));
when(mLonElement.getText()).thenReturn(
    Float.toString(A_LOCATION_BEAN.getLon()));

// let it work!
GeoLocationFetcher geoLocationFetcher = GeoLocationFetcher
    .getInstance();
LocationBean locationBean = geoLocationFetcher
    .extractGeoLocationFromXml(mDocument);

// verify their behavior
verify(mDocument).getRootElement();
verify(mRootElement).getChild("geoname");
verify(mGeonameElement).getChild("lat");
verify(mGeonameElement).getChild("lon");
verify(mLatElement).getText();
verify(mLonElement).getText();

assertEquals(A_LOCATION_BEAN, locationBean);

Ce que montre mon code, c’est que j’ai effectué un "micro-test". l'objet de consommation. C'est comme si j'implémentais mon code productif dans mon test. Un exemple de résultat xml est London on GeoNames . À mon avis, c'est beaucoup trop granulaire.

Mais comment puis-je me moquer d'un service Web sans me donner de cesse? Devrais-je laisser l'objet fictif simplement renvoyer un fichier XML?

Cela ne concerne pas le code, mais l'approche .

J'utilise JUnit 4.x et Mockito 1.7

Était-ce utile?

La solution

vous voulez vraiment vous moquer des résultats renvoyés par le service Web au code qui les utilisera. Dans l'exemple de code ci-dessus, vous semblez vous moquer de mDocument, mais vous souhaitez réellement transmettre une instance de mDocument renvoyée à partir d'une instance simulée de votre service Web et affirmer que l'emplacementBean renvoyé par geoLocationFetcher correspond à la valeur de A_LOCATION_BEAN.

Autres conseils

Je pense que le vrai problème ici est que vous avez un singleton qui appelle et crée le service Web, il est donc difficile d’en insérer un faux.

Vous devrez peut-être ajouter (éventuellement au niveau du package) un accès à la classe singleton. Par exemple, si le constructeur ressemble à quelque chose comme

private GeoLocationFactory(WebService service) {
   ...
}

vous pouvez créer le niveau de package constructeur et en créer un avec un service Web simulé.

Vous pouvez également définir le service Web en ajoutant une méthode de définition, bien que je n'aime pas les singletons mutables. Dans ce cas également, vous devez vous rappeler de désactiver le service Web par la suite.

Si le service Web est créé selon une méthode, vous devrez peut-être rendre GeoLocationFactory extensible pour remplacer le service fictif.

Vous pouvez également chercher à supprimer le singleton lui-même. Il existe des articles en ligne et probablement ici sur la façon de le faire.

L'option la plus simple serait de se moquer du client WebService,

when(geoLocationFetcher.extractGeoLocationFromXml(anyString()))
    .thenReturn("<location/>");

Vous pouvez modifier le code pour lire la réponse XML à partir du système de fichiers.

Vous trouverez un exemple de code ici: Mocking .NET WebServices avec Mockito

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top