Подтвердить что ты не робот

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");
}
4b9b3361

Ответ 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.