对于JUnit测试,我想模拟一个重载的方法。不过,没有必要在mockbuilder中实现几个方法。我想做这样的事情:
Mockito.when(mock.getSomeInfo(Mockito.any(ArgumentType1.class) OR Mockito.any(ArgumentType2.class), Mockito.any(ArgumentType3.class))).then(new Answer<AnswerType>() {..}
我知道它不适用于OR
语句,但在Mockito中有其他方法可以做到这一点吗?
如mockito github上所述:
这似乎与第二次打电话有关。我找不到发生了什么,但第二次没有尝试添加mock逻辑,它只是调用了方法用doReturn()替换。when()有效
doReturn(expected1).when(overloadedMethods).getString(any());
doReturn(expected2).when(overloadedMethods).getString(any(), any());
https://github.com/mockito/mockito/issues/1496#issuecomment-423310950 DavidTanner
您可以使用自定义匹配器来完成此操作。
警告:使用复杂的参数匹配要合理,尤其是自定义参数匹配器,因为这会降低测试的可读性。有时,最好为传递给mock的参数实现equals()(Mockito自然会使用equals(()进行参数匹配)。这样可以使测试更干净。
public class TypeOrMatcher extends ArgumentMatcher<Object> {
private final List<Class<?>> clazzes;
public TypeOrMatcher(Class<?>...clazzes) {
this.clazzes = new ArrayList<Class<?>>(clazzes);
}
public boolean matches(Object actual) {
if (actual == null) {
return false;
}
Class<?> actualClass = actual.getClass();
for (Class<?> clazz : clazzes) {
if (clazz.isAssignableFrom(actualClass) {
return true;
}
}
return false;
}
}
TypeOrMatcher isTypeOneOrTwo = new TypeOrMatcher(
ArgumentType1.class, ArgumentType2.class);
Some mockObj = mock(Some.class);
when(mockObj.someMethod(argThat(isTypeOneOrTwo), any(ArgumentType3.class))
.thenReturn(true);
您可以预先创建要返回的答案对象,然后返回此答案。
class A {
public int test(final String s) {
return 0;
}
public int test(final int i) {
return 0;
}
}
并且在测试方法中:
public void testAtest() {
final A a = Mockito.mock(A.class);
final Answer<Integer> answer = new Answer<Integer>() {
@Override
public Integer answer(final InvocationOnMock invocation) throws Throwable {
return 0;
}
};
Mockito.when(a.test(Matchers.anyInt())).then(answer);
Mockito.when(a.test(Matchers.anyString())).then(answer);
}
例如,我有一个将从测试方法调用的服务类:
public interface AService{
public ReturnObject addNewItem(String param1, String param2);
public ReturnObject addNewItem(String param1, String param2, boolean isOk);
}
MainServiceImpl类中有一个方法将调用一个重载方法,如下所示:
@Service("mainService")
public class MainServiceImpl implements MainService {
@Autowired
private AService aService;
public ReturnObject saveItem(String itemName, String itemCode){
return aService.addNewItem(itemName, itemCode);
}
}
因此,当我们必须为saveItem
编写单元测试时,该方法已经将重载方法调用为addNewItem
,如果您使用正常方式创建mock,那么您的答案将不会在答案对象返回中返回您想要的内容。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ })
public class ItemTest{
@Test
public void testSaveItem() throws Exception {
//create a real object of MainServiceImpl
MainServiceImpl mainService = new MainServiceImpl();
//create a normal way for a mocking object
AService aService = Mockito.mock(AService.class);
// Add mock object to MainServiceImpl instance
ReflectionTestUtils.setField(mainService, "aService", aService);
//Mock when aService call to addNewItem() method
PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
@Override
public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
});
ReturnObject returnObj = mainService.saveItem("Book", "Code123");
Assert.assertNotNull(returnObj);
}
}
尝试用以下testSaveItem替换上面的testSaveItem,然后成功:
@Test
public void testSaveItem() throws Exception {
//create a real object of MainServiceImpl
MainServiceImpl mainService = new MainServiceImpl();
//create a special way for a mocking object by add
//the answer at create the mock object
final Answer<ReturnObject> answer = new Answer<ReturnObject>() {
@Override
public ReturnObjectanswer(final InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
};
AService aService = Mockito.mock(AService.class, answer);
// Add mock object to MainServiceImpl instance
ReflectionTestUtils.setField(mainService, "aService", aService);
//Mock when aService call to addNewItem() method
PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
@Override
public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
});
ReturnObject returnObj = mainService.saveItem("Book", "Code123");
Assert.assertNotNull(returnObj);
}