How can I mock a Google geocoding API request using mockito / powermock?

I want to use unit test this method using 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; } } 

here is what i tried:

 @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); } } 

I get a NullPointerException. Here is the stack trace:

 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) 

is in the wait call line ()

EDIT: this is how it looks now, it still doesn't work

btw, @RunWith(PowerMockRunner.class) is 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); } 

and 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) 

Thank you in advance

+5
source share
1 answer

There are a few mistakes here, and this shows that you misunderstand the mockery. Let them analyze them:

At first, I hope this is a mistake with the last error, you do not have @RunWith(PowerMockRunner.class) , otherwise you will get one more exception.

The second point, this line is commented out correctly when(GeocodingApi.newRequest(geoApiContext)).thenReturn(geocodingApiRequest); . When the static method is GeocodingApi , then you want to return geocodingApiRequest .

Finally, but the most important point, this line is incorrect: when(GeocodingApi.newRequest(geoApiContext).latlng(latLng).await()).thenReturn(geocodingResults);

Only one static call will laugh here: GeocodingApi.newRequest(geoApiContext) .

And the instance of the actual object will be returned, because you are creating a new instance of GeocodingApiRequest geocodingApiRequest = new GeocodingApiRequest(geoApiContext); .

The latlng(latLng) method is called from a valid object. And he really calls, not mocks. But it seems to me that you also want to mock it.

Then let's cast it: GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class);

After. make fun of all the challenges you need to mock:

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

Another error, but as important as the previous and more obvious: the required files are not installed for geocodingResult .

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

Full working test:

 @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); } } 
+4
source

Source: https://habr.com/ru/post/1243904/


All Articles