2015-02-03 6 views
0

Я пытаюсь использовать mockito для издевательства над методом. Однако класс, который я вводил, издевается над вызовом метода дважды при отправке в два разных объекта одного и того же типа, но в зависимости от значений в объекте определяет выход метода.Mockito Mock вызов метода, вызываемый дважды

Так, например, если я пытаюсь издеваться

public ArrayList<example> attemptToMock(testObject testing) 

Препятствует сидел тип testObject имеет строковое значение в нем.

Так что если строковое значение в testObject равно «ОК», то attemptToMock должно выводить в него массив из двух объектов. Если testObject строковое значение «НЕТ», то в списке массивов, отправленном только один объект.

Как написать тест для обработки вызова, чтобы класс мог вызвать attemptToMock дважды в том же методе, и я могу издеваться над его выходом так, чтобы он зависел от значений в пределах testObject. Я могу высмеять его, чтобы отправить различные массивы.

ответ

1

Несколько вариантов:

  • Override equals and hashCode на ваш объект (TestObject). Это возможно только в том случае, если все значения на вашем объекте предсказуемы и могут быть более эффективными, чем другие решения, но если вам нужно писать equals и hashCode в любом случае (например, для поведения карты и набора), это разумное решение.

    // Mockito compares with objects' equals(Object) methods by default. 
    when(collaborator.attemptToMock(object1)).thenReturn(array1); 
    when(collaborator.attemptToMock(object2)).thenReturn(array2); 
    
  • Написать Hamcrest matcher и использовать, чтобы соответствовать массивы. Это действует как компактный аналог equals для конкретного случая и особенно удобен, если вам нужно изменить поведение, основанное на одном и том же значении во многих тестах.

    public class IsATestObjectWithValue extends TypeSafeMatcher<TestObject> { 
        private final String expectedValue; 
    
        public IsATestObjectWithValue(String expectedValue) { 
        super(TestObject.class); 
        this.expectedValue = expectedValue; 
        } 
    
        @Override public void matchesSafely(TestObject object) { 
        // object will never be null, but object.value might. 
        return expectedValue.equals(object.value); 
        } 
    } 
    

    Теперь вы можете написать эквивалентный матч, как описано выше:

    when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("OK"))) 
        .thenReturn(array1); 
    when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("NO"))) 
        .thenReturn(array2); 
    
  • Используйте ответ, as wdf described. Анонимные внутренние ответы являются общими и довольно краткими, и вы получаете доступ ко всем аргументам. Это особенно полезно для одноразовых решений или если вы хотите явно и немедленно пропустить тест, если передано недопустимое значение (testObject.value).

  • В крайнем случае, если порядок вызовов является предсказуемым, вы можете последовательно возвращать несколько значений.

    when(collaborator.attemptToMock(any(TestObject.class))) 
        .thenReturn(array1).thenReturn(array2); 
    when(collaborator.attemptToMock(any(TestObject.class))) 
        .thenReturn(array1, array2); // equivalent 
    

    либо из вышеуказанных строк будет возвращать array1 для первого вызова и array2 для второго вызова и всех вызовов, после него, независимо от параметра. Это решение будет гораздо более хрупким, чем ваш первоначальный вопрос запрашивает - он будет терпеть неудачу, если порядок звонков изменится или если любой из звонков отредактирован или повторен - но иногда это самое компактное решение, если тест является очень временным или если заказ абсолютно фиксирован.

0

Вы можете получить доступ к параметрам, переданным в вызове издевающегося метода, и соответственно изменить возвращаемое значение с помощью интерфейса ответа. См. Ответ this question и the docs for Answer.

В принципе, единственная странная/неочевидная вещь, которая здесь происходит, заключается в том, что вам нужно свести параметры к типу, который вы ожидаете. Таким образом, в вашем случае, если вы насмехаясь метод, который принимает один параметр «TestObject», то вы должны сделать что-то вроде этого внутри вашей «ответ» реализации:

Object[] args = invocation.getArguments(); 
TestObject testObj = (TestObject) args[0]; 
if ("OK".equals(testObj.value)) { 
    return new ArrayList(value1, value2); 
} else if ("NO".equals(testObj.value)) { 
    return new ArrayList(singleObject); 
} 
Смежные вопросы