Mockito возвращает значение, основанное на свойстве параметра
Обычно при использовании mockito я буду делать что-то вроде
Mockito.when(myObject.myFunction(myParameter)).thenReturn(myResult);
Можно ли что-то делать по линиям
myParameter.setProperty("value");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("myResult");
myParameter.setProperty("otherValue");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("otherResult");
Итак, вместо того, чтобы просто использовать параметр для определения результата. Он использует значение свойства внутри параметра для определения результата.
поэтому, когда код выполняется, он ведет себя так:
public void myTestMethod(MyParameter myParameter,MyObject myObject){
myParameter.setProperty("value");
System.out.println(myObject.myFunction(myParameter));// outputs myResult
myParameter.setProperty("otherValue");
System.out.println(myObject.myFunction(myParameter));// outputs otherResult
}
текущее решение, мы надеемся, что можно предложить что-то лучшее.
private class MyObjectMatcher extends ArgumentMatcher<MyObject> {
private final String compareValue;
public ApplicationContextMatcher(String compareValue) {
this.compareValue= compareValue;
}
@Override
public boolean matches(Object argument) {
MyObject item= (MyObject) argument;
if(compareValue!= null){
if (item != null) {
return compareValue.equals(item.getMyParameter());
}
}else {
return item == null || item.getMyParameter() == null;
}
return false;
}
}
public void initMock(MyObject myObject){
MyObjectMatcher valueMatcher = new MyObjectMatcher("value");
MyObjectMatcher otherValueMatcher = new MyObjectMatcher("otherValue");
Mockito.when(myObject.myFunction(Matchers.argThat(valueMatcher))).thenReturn("myResult");
Mockito.when(myObject.myFunction(Matchers.argThat(otherValueMatcher))).thenReturn("otherResult");
}
Ответы
Ответ 1
Вот один из способов сделать это. Для проверки значения свойства используется объект Answer
.
@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
private String theProperty;
@Mock private MyClass mockObject;
@Before
public void setUp() {
when(mockObject.myMethod(anyString())).thenAnswer(
new Answer<String>(){
@Override
public String answer(InvocationOnMock invocation){
if ("value".equals(theProperty)){
return "result";
}
else if("otherValue".equals(theProperty)) {
return "otherResult";
}
return theProperty;
}});
}
}
Есть альтернативный синтаксис, который я действительно предпочитаю, который достигнет точно такой же. К вам, какой из них вы выберете. Это всего лишь метод setUp
- остальная часть тестового класса должна быть такой же, как и выше.
@Before
public void setUp() {
doAnswer(new Answer<String>(){
@Override
public String answer(InvocationOnMock invocation){
if ("value".equals(theProperty)){
return "result";
}
else if("otherValue".equals(theProperty)) {
return "otherResult";
}
return theProperty;
}}).when(mockObject).myMethod(anyString());
}
Ответ 2
В Java 8 это еще проще, чем все вышесказанное:
when(mockObject.myMethod(any(parameterClass.class)))
.thenAnswer(
invocation -> {
if (invocation.getArgumentAt(0, parameterClass.class))).equals(myParameter)){
return MockedReturn;
}
return null;
}
Ответ 3
Да, вы можете использовать пользовательский аргумент.
Подробнее см. javadoc Matchers
, а точнее ArgumentMatcher
.