2016-01-10 191 views
1

我有2個類互動。 說ServiceLayer.classApiAdaptor.class如何使用powermock部分模擬外部方法調用

public class ApiAdaptor { 
    public String getCountry(String latitude, String longitude) { 
    // REST call to api goes here and a the country string is returned 
    return country; 
    } 
} 

public class ServiceLayer { 
public String findCountry(int positionId) { 
    // some business logic here to get latitude and longitude from postitionId 
    ApiAdaptor api = new ApiAdaptor(); 
    String country = api.getCountry(latitude, longitude); 
    return country; 
} 
} 

現在在單元測試,我只需要測試這種方法ServiceLayer.findcountry(),而嘲諷內部調用ApiAdaptor.getCountry(latitude, longitude)。有什麼辦法可以使用Powermock來做到這一點。在Ruby On Rails中使用Rspec時,我看到了類似的stubing。我想在我的java-SpringMVC項目中做類似的測試。

回答

1

當然,您可以使用PowerMock只專注於該方法。例如,使用PowerMockito具體情況,你可以這樣寫測試:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ServiceLayer.class}) 
public class PowerMockitoJan10Test { 
    private static final java.lang.String DESIRED_COUNTRY_VALUE = "USA"; 

    @Test 
    public void testServiceLayerFindCountry() throws Exception { 
     ApiAdaptor mock = Mockito.mock(ApiAdaptor.class); 
     PowerMockito.whenNew(ApiAdaptor.class).withAnyArguments().thenReturn(mock); 
     Mockito.when(mock.getCountry(Mockito.anyString(), Mockito.anyString())).thenReturn(DESIRED_COUNTRY_VALUE); 

     String country = new ServiceLayer().findCountry(1); 
     Assert.assertEquals(DESIRED_COUNTRY_VALUE, country); 
    } 
} 

如果你使用Spring,很可能是你需要一個JUnit運行,所以你可以使用PowerMockito JUnit的規則,而 - see this example


編輯:這是有趣的。使用規則時,除非您將ServiceLayer.class添加到@PrepareForTest列表中,否則它確實無法正常工作。在撰寫本文時,我使用了最新的PowerMockito版本1.6.4。可能值得報告。在任何情況下,這是你的測試將如何與Spring工作:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("mycontext.xml") 
@PrepareForTest({ApiAdaptor.class, ServiceLayer.class}) 
public class PowerMockitoJan10_WithRuleTest { 
    private static final String DESIRED_COUNTRY_VALUE = "USA"; 

    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    @Test 
    public void testServiceLayerFindCountry() throws Exception { 
     PowerMockito.whenNew(ApiAdaptor.class).withNoArguments().thenReturn(new ApiAdaptor() { 
      @Override 
      public String getCountry(String latitude, String longitude) { 
       return DESIRED_COUNTRY_VALUE; 
      } 
     }); 

     String country = new ServiceLayer().findCountry(1); 
     Assert.assertEquals(DESIRED_COUNTRY_VALUE, country); 
    } 

} 

或者,如果覆蓋是一個問題,你可以嘲笑ApiAdaptor

... 
    ApiAdaptor mock = PowerMockito.mock(ApiAdaptor.class); 
    PowerMockito.when(mock.getCountry(Mockito.anyString(), Mockito.anyString())).thenReturn(DESIRED_COUNTRY_VALUE); 
    PowerMockito.whenNew(ApiAdaptor.class).withNoArguments().thenReturn(mock); 
    ... 
+0

我正在做同樣的事情,但是當我運行測試時,沒有調用stubbed方法並且完成的方法運行... :( – ishanbakshi

+0

我的註釋配置是這樣的: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @PrepareForTes t({ServiceLayer.class}) – ishanbakshi

+0

你是對的,它不能像切換到規則時那樣工作。但是我在註釋列表中添加了'ServiceLayer.class',它現在運行良好。 –

0

如果你可以改變你的代碼,我d建議你通過在你的類上進行依賴注入來使其更具可測性。

您將有類似的東西:

public class ServiceLayer { 
    private ApiAdaptor _api; 
    public ServiceLayer(ApiAdaptor api) { 
     _api = api; 
    } 
    [snip] 
} 

然後在你的代碼的其餘部分使用_api

當你需要測試這個類,如果你有嘲笑ApiAdaptor,你可以寫信:

ApiAdaptor mock = Mockito.mock(ApiAdaptor.class); 
[Api adaptor behavior mocking] 
String country = new ServiceLayer(mock).findCountry(1); 
[asserts and all] 

這消除了PowerMockito,其跑步者和/或規則...

需要
+0

爲suggesstions thnks ...我目前正在做依賴注入,但我覺得在將來的某個時刻,我將不得不使用功率模擬,因爲我無法繼續聲明類變量......這就是爲什麼我正在尋找一個特定於功率模擬或類似庫的解決方案 – ishanbakshi

+0

如果你開始有太多的依賴關係,也許它可以幫助添加一個包含一些變量的類。一些依賴關係可能比類依賴關係更有意義作爲方法參數。 – SKBo

相關問題