我有2个班级互动。
说ServiceLayer.class
和ApiAdaptor.class
:
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时遇到过类似的存根。我想在我的java-SpringMVC项目中进行类似的测试。
答案 0 :(得分: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);
...
答案 1 :(得分:0)
如果您可以更改代码,我建议您通过在类上进行依赖注入来使其更易于测试。
你会有类似的东西:
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及其跑步者和/或规则的需求......