2016-02-26 14 views
5

Tôi muốn kiểm tra đơn vị sử dụng phương pháp này Mockito/powermock:Tôi có thể thử yêu cầu API mã hóa địa lý của Google bằng cách sử dụng mockito/powermock như thế nào?

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

} 

đây là những gì tôi đã cố gắng:

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

} 

tôi nhận được NullPointerException. Dưới đây là 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) 

là trong dòng chờ đợi() gọi

EDIT: đây là cách có vẻ bây giờ, nó vẫn không làm việc

btw, @RunWith(PowerMockRunner.class) là trong 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); 

} 

và ngăn xếp:

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) 

Cảm ơn trước

+0

Bạn có thể thêm null con trỏ stack trace? –

+0

@NickDeFazio thực hiện –

Trả lời

3

Có một số lỗi ở đây và cho thấy bạn có hiểu lầm về chế nhạo. Hãy phân tích chúng:

Lúc đầu, tôi hy vọng đó là lỗi quá khứ đã sao chép, bạn không có @RunWith(PowerMockRunner.class), nếu không bạn sẽ nhận được một ngoại lệ khác.

Điểm thứ hai, dòng nhận xét này là đúng when(GeocodingApi.newRequest(geoApiContext)).thenReturn(geocodingApiRequest);. Khi phương pháp tĩnh của GeocodingApi thì bạn muốn trả lại geocodingApiRequest.

Cuối cùng, nhưng điểm quan trọng nhất, dòng này là không chính xác: when(GeocodingApi.newRequest(geoApiContext).latlng(latLng).await()).thenReturn(geocodingResults);

Chỉ có một cuộc gọi tĩnh sẽ được chế giễu ở đây: GeocodingApi.newRequest(geoApiContext).

Và trường hợp đối tượng thực sự sẽ trở lại, vì bạn tạo một phiên bản mới GeocodingApiRequest geocodingApiRequest = new GeocodingApiRequest(geoApiContext);.

Phương thức latlng(latLng) được gọi từ đối tượng thực sự. Và nó thực sự gọi, không bị chế giễu. Nhưng có vẻ với tôi bạn cũng muốn thử nó.

Sau đó, giả sử nó: GeocodingApiRequest geocodingApiRequest = mock(GeocodingApiRequest.class);

Sau. giả tất cả các cuộc gọi mà cần phải được chế giễu:

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

Một sai lầm, nhưng rất quan trọng như trước và rõ ràng hơn: các file cần thiết không được thiết lập cho geocodingResult.

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

Các thử nghiệm làm việc đầy đủ:

@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

cảm ơn, nó giúp, nhưng vẫn không hoạt động, tôi vẫn nhận được NPE đang chờ() gọi, tôi đã chỉnh sửa bài kiểm tra của tôi (xem chỉnh sửa trả lời) và sao chép/dán giải pháp của bạn cùng một dòng. –

+0

Bạn đã thêm 'GeocodingApiRequest.class' vào '@PrepareForTest' chưa? –

+0

ồ, tôi quên mất, nhưng tôi đã thêm vào và vẫn không hoạt động .. cùng lỗi –

Các vấn đề liên quan