Domanda

Sto implementando un client che utilizza un servizio web. Voglio ridurre le dipendenze e ho deciso di deridere il servizio web.
Uso mockito , ha il vantaggio rispetto a EasyMock di essere in grado di deridere classi, non solo interfacce. Ma non è questo il punto.

Nel mio test, ho questo codice:

// 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);

Ciò che mostra il mio codice è che "test micro". l'oggetto consumante. È come se implementassi il mio codice produttivo nel mio test. Un esempio per il risultato xml è London on GeoNames . Secondo me, è troppo granulare.

Ma come posso deridere un servizio web senza dare everystep? Devo lasciare che l'oggetto finto restituisca solo un file XML?

Non si tratta del codice, ma dell'approccio .

Sto usando JUnit 4.xe Mockito 1.7

È stato utile?

Soluzione

vuoi davvero deridere i risultati restituiti dal servizio web al codice che utilizzerà il risultato. Nel tuo codice di esempio sopra sembra deridere mDocument ma vuoi davvero passare un'istanza di mDocument che è stata restituita da un'istanza derisa del tuo servizio web e asserire che locationBean restituito da geoLocationFetcher corrisponde al valore di A_LOCATION_BEAN.

Altri suggerimenti

Penso che il vero problema qui sia che hai un singleton che chiama e crea il servizio web, quindi è difficile inserirne uno finto.

Potrebbe essere necessario aggiungere (possibilmente a livello di pacchetto) l'accesso alla classe singleton. Ad esempio se il costruttore ha un aspetto simile a

private GeoLocationFactory(WebService service) {
   ...
}

puoi rendere il livello del pacchetto di costruzione e crearne uno con un servizio Web deriso.

In alternativa puoi impostare il servizio web aggiungendo un metodo setter, anche se non mi piacciono i Singleton mutabili. Anche in quel caso devi ricordarti di disinserire il servizio web in seguito.

Se il servizio web viene creato con un metodo, potrebbe essere necessario estendere GeoLocationFactory per sostituire il servizio di simulazione.

Puoi anche cercare di rimuovere il singleton stesso. Ci sono articoli online e probabilmente qui su come farlo.

L'opzione più semplice sarebbe quella di deridere il client WebService,

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

È possibile modificare il codice per leggere la risposta xml dal file system.

Il codice di esempio è disponibile qui: Mocking .NET Servizi Web con Mockito

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top