2016-02-26 48 views
5

我想要的单元测试使用的Mockito/powermock这种方法:如何使用mockito/powermock模拟Google的Geocoding API请求?

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

} 

这是我曾尝试:

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

} 

我得到NullPointerException异常。这里是堆栈跟踪:

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) 

在的await()调用线

编辑:这是现在的样子,现在还没有工作

顺便说一句,@RunWith(PowerMockRunner.class)是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); 

} 

和堆栈:

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) 

在此先感谢

+0

您可以添加空指针堆栈跟踪? –

+0

@NickDeFazio完成 –

回答

3

这里有几个错误,它表明你有误解的嘲笑。让我们分析一下:

起初,我希望它是复制过去的错误,你没有@RunWith(PowerMockRunner.class),否则你会得到另一个例外。

第二点,这个注释掉的行是对的when(GeocodingApi.newRequest(geoApiContext)).thenReturn(geocodingApiRequest);。当GeocodingApi的静态方法时,则要返回geocodingApiRequest

最后,但最重要的一点,这条线是不正确的:when(GeocodingApi.newRequest(geoApiContext).latlng(latLng).await()).thenReturn(geocodingResults);

只有一个静态的通话将被嘲笑这里:GeocodingApi.newRequest(geoApiContext)

而真实对象的实例将被返回,因为您创建了一个新实例 GeocodingApiRequest geocodingApiRequest = new GeocodingApiRequest(geoApiContext);

latlng(latLng)方法是从真正的对象中调用的。这是真正的电话,而不是嘲笑。但在我看来,你也想嘲笑它。

然后让我们嘲笑它:GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class);

后。需要模拟所有呼叫被嘲笑:

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

另一个错误,但由于以前的多明明那么重要:所需的文件没有设置geocodingResult

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

完整的工作测试:

@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

谢谢,它有帮助,但仍然不工作,我仍然在等待()呼叫,我编辑了我的测试(请参阅编辑答案),还复制/粘贴您的解决方案,都失败了同一条线。 –

+0

您是否已将'GeocodingApiRequest.class'添加到'@PrepareForTest'? –

+0

哦,我忘了,但我现在加了,仍然没有工作..同样的错误 –