2016-02-26 13 views
5

Voglio unit test utilizzando questo metodo Mockito/powermock:Come posso prendere in giro la richiesta dell'API di Geocoding di Google utilizzando mockito/powermock?

@Service 
public class GoogleApiService { 

    private static final Logger logger = LoggerFactory.getLogger(GoogleApiService.class); 

    private static final String LANGUAGE = "es"; 

    private List<AddressType> addressTypes = Arrays.asList(
      AddressType.LOCALITY, 
      AddressType.ADMINISTRATIVE_AREA_LEVEL_2, 
      AddressType.ADMINISTRATIVE_AREA_LEVEL_1, 
      AddressType.COUNTRY 
    ); 

    @Autowired 
    private GeoApiContext geoApiContext; 

    public String getLocalityFromLatLng(LatLng latLng) throws Exception { 
     logger.debug("getLocalityFromLatLng"); 

     GeocodingResult[] geocodingResults = GeocodingApi.newRequest(geoApiContext) 
      .latlng(latLng) 
      .await(); 
     for (GeocodingResult geocodingResult : geocodingResults) { 
      AddressType addressType = geocodingResult.types[0]; 
      if (addressTypes.contains(addressType)) { 
       return geocodingResult.formattedAddress; 
      } 
     } 
     return StringUtils.EMPTY; 
    } 

} 

questo è quello che ho provato:

@PrepareForTest(GeocodingApi.class) 
public class GoogleApiServiceUnitTest extends AbstractUnitTest { 

    private static final Double LATITUDE = -38.010403; 
    private static final Double LONGITUDE = -57.558408; 

    @Mock 
    private GeoApiContext geoApiContext; 

    @InjectMocks 
    private GoogleApiService googleApiService; 

    @Test 
    public void testGetLocalityFromLatLng() throws Exception { 

     LatLng latLng = new LatLng(LATITUDE, LONGITUDE); 
     GeocodingResult geocodingResult = new GeocodingResult(); 
     GeocodingResult[] geocodingResults = new GeocodingResult[] { geocodingResult }; 

     GeocodingApiRequest geocodingApiRequest = new GeocodingApiRequest(geoApiContext); 
     geocodingApiRequest.latlng(latLng); 

     mockStatic(GeocodingApi.class); 

     // when(GeocodingApi.newRequest(geoApiContext)) 
      // .thenReturn(geocodingApiRequest); 

     // when(GeocodingApi.newRequest(geoApiContext).latlng(latLng)) 
      // .thenReturn(geocodingApiRequest); 

     when(GeocodingApi.newRequest(geoApiContext).latlng(latLng).await()) 
      .thenReturn(geocodingResults); 

     String locality = googleApiService.getLocalityFromLatLng(latLng); 

     assertThat(locality, is(notNullValue())); 

     verifyStatic(times(1)); 
     GeocodingApi.newRequest(geoApiContext).latlng(latLng).await(); 

     verifyNoMoreInteractions(geoApiContext); 
    } 

} 

sto ottenendo NullPointerException. Ecco l'analisi dello stack:

java.lang.NullPointerException 
at com.google.maps.PendingResultBase.await(PendingResultBase.java:56) 
at com.beermap.server.unit.service.GoogleApiServiceUnitTest.testGetLocalityFromLatLng(GoogleApiServiceUnitTest.java:57) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310) 
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89) 
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) 
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87) 
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) 
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) 
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106) 
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

è in prima linea await) chiamata (

EDIT: questo è come appare ora, non è ancora funzionante

btw, @RunWith(PowerMockRunner.class) è in AbstractUnitTest

@Test 
public void testGetLocalityFromLatLng() throws Exception { 

    LatLng latLng = new LatLng(LATITUDE, LONGITUDE); 
    GeocodingResult geocodingResult = new GeocodingResult(); 
    geocodingResult.types = new AddressType[] { AddressType.LOCALITY }; 
    geocodingResult.formattedAddress = FORMATTED_ADDRESS; 
    GeocodingResult[] geocodingResults = new GeocodingResult[] { geocodingResult }; 

    GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class); 

    mockStatic(GeocodingApi.class); 

    when(geocodingApiRequest.latlng(latLng)).thenReturn(geocodingApiRequest); 
    when(geocodingApiRequest.await()).thenReturn(geocodingResults); // NPE here 
    when(GeocodingApi.newRequest(geoApiContext)).thenReturn(geocodingApiRequest); 

    String locality = googleApiService.getLocalityFromLatLng(latLng); 

    assertThat(locality, is(notNullValue())); 

    // verifyStatic(times(1)); 
    // GeocodingApi.newRequest(geoApiContext).latlng(latLng).await(); 

    // verifyNoMoreInteractions(geoApiContext); 

} 

e lo stack:

java.lang.NullPointerException 
at com.google.maps.PendingResultBase.makeRequest(PendingResultBase.java:79) 
at com.google.maps.PendingResultBase.await(PendingResultBase.java:55) 
at com.beermap.server.unit.service.GoogleApiServiceUnitTest.testGetLocalityFromLatLng(GoogleApiServiceUnitTest.java:56) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310) 
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89) 
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) 
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87) 
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) 
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) 
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) 
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122) 
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106) 
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

Grazie in anticipo

+0

si può aggiungere il nulla traccia stack pointer? –

+0

@NickDeFazio fatto –

risposta

3

Ci sono diversi errori qui e mostra che si hanno fraintendimenti di derisione. Analizzali:

All'inizio, spero che sia un errore di copia, non hai @RunWith(PowerMockRunner.class), altrimenti otterrai un'altra eccezione.

Secondo punto, questa linea commentata è corretta when(GeocodingApi.newRequest(geoApiContext)).thenReturn(geocodingApiRequest);. Quando si utilizza il metodo statico di GeocodingApi, si desidera restituire geocodingApiRequest.

Alla fine, ma il punto più importante, questa linea non è corretto: when(GeocodingApi.newRequest(geoApiContext).latlng(latLng).await()).thenReturn(geocodingResults);

una sola chiamata statica verrà preso in giro qui: GeocodingApi.newRequest(geoApiContext).

E l'istanza di oggetto reale verrà restituita, perché si crea una nuova istanza GeocodingApiRequest geocodingApiRequest = new GeocodingApiRequest(geoApiContext);.

Il metodo latlng(latLng) viene chiamato dall'oggetto realmente. Ed è davvero chiamata, non derisa. Ma a me sembra che voglia anche deriderlo.

Poi lasciate Mock è: GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class);

Dopo. finti tutte le chiamate che devono essere presi in giro:

when(geocodingApiRequest.latlng(latLng)).thenReturn(geocodingApiRequest); 
when(geocodingApiRequest.await()).thenReturn(geocodingResults); 

Un altro errore, ma così importanti da precedenti e più evidente: i file necessari non sono destinati per il geocodingResult.

GeocodingResult geocodingResult = new GeocodingResult(); 
geocodingResult.types = new AddressType[]{ AddressType.LOCALITY}; 
geocodingResult.formattedAddress = "Some address"; 

Il test di funzionamento completo:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({GeocodingApi.class, GeocodingApiRequest.class}) 
public class GoogleApiServiceUnitTest { 

    private static final Double LATITUDE = -38.010403; 
    private static final Double LONGITUDE = -57.558408; 

    @Mock 
    private GeoApiContext geoApiContext; 

    @InjectMocks 
    private GoogleApiService googleApiService; 

    @Test 
    public void testGetLocalityFromLatLng() throws Exception { 

     LatLng latLng = new LatLng(LATITUDE, LONGITUDE); 
     GeocodingResult geocodingResult = new GeocodingResult(); 
     geocodingResult.types = new AddressType[]{ AddressType.LOCALITY}; 
     geocodingResult.formattedAddress = "Some address"; 

     GeocodingResult[] geocodingResults = new GeocodingResult[] { geocodingResult }; 

     GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class); 
     when(geocodingApiRequest.latlng(latLng)).thenReturn(geocodingApiRequest); 
     when(geocodingApiRequest.await()).thenReturn(geocodingResults); 

     mockStatic(GeocodingApi.class); 

     when(GeocodingApi.newRequest(eq(geoApiContext))) 
      .thenReturn(geocodingApiRequest); 

     String locality = googleApiService.getLocalityFromLatLng(latLng); 

     assertThat(locality, is(notNullValue())); 

     verifyStatic(times(1)); 
     GeocodingApi.newRequest(geoApiContext); 

     // add verification other mock if you really need it 

     verifyNoMoreInteractions(geoApiContext); 
    } 
} 
+0

grazie, aiuta, ma non funziona ancora, sto ancora ricevendo NPE in attesa() chiamata, ho modificato il mio test (vedi modifica in risposta) e anche copia/incolla la tua soluzione, ed entrambi falliscono la stessa linea. –

+0

Hai aggiunto "GeocodingApiRequest.class" a "@PrepareForTest"? –

+0

oh, ho dimenticato, ma ho aggiunto ora e non funziona ancora. Stesso errore –

Problemi correlati