Как обрабатывать непревзойденные параметры в Mockito?
Мне нравится делать что-то вроде следующего:
.when(
myMock.doSomething(
Matchers.eq( "1" )
)
)
.thenReturn( "1" )
.othwerwise()
.thenThrow( new IllegalArgumentException() );
Конечно, метод otherwise()
не существует, а просто для того, чтобы показать вам, чего я хочу достичь.
Ответы
Ответ 1
(Немного оговорки, я никогда не делал этого лично, просто читал об этом в javadoc)... Если бы все ваши методы на вашем макетном интерфейсе были бы в порядке с одинаковым поведением по умолчанию, вы могли бы установить ответ по умолчанию на ваш макет таким образом, как:
Foo myMock = Mockito.mock(Foo.class,new ThrowsExceptionClass(IllegalArgumentException.class));
Mockito.when(myMock.doSomething(Matchers.eq("1"))).thenReturn("1");
JavaDoc Ссылки для: Mockito # mock и ThrowsExceptionClass
В качестве альтернативы, как обсуждается в Учебное пособие по обучению, порядок вопросов об окончании и последних совпадений, так что вы также сможете сделать
Foo myMock = Mockito.mock(Foo.class);
Mockito.when(myMock.doSomething(Matchers.any(String.class))).thenThrow(IllegalArgumentException.class);
Mockito.when(myMock.doSomething(Matchers.eq("1"))).thenReturn("1");
Ответ 2
вы могли бы создать свою собственную реализацию ответа, которая обратила бы внимание на вызываемые параметры:
myMock.doSomething(Mockito.any(String.class)).thenAnswer( myAnswer );
Реализация указанного ответа может сделать примерно следующее:
public String answer(InvocationOnMock invocation) {
if ("1".equals(invocation.getArguments()[0])) {
return "1";
}
else {
throw new IllegalArgumentException();
}
}
Ответ 3
Просто используйте противоположное условие, то есть рассмотрите свой пример. Вы можете использовать not(eq())
, когда вам нужно otherwise
:
.when( myMock.doSomething(Matchers.eq( "1" )))
.thenReturn( "1" )
.when( myMock.doSomething(not(Matchers.eq( "1" ))))
.thenThrow( new IllegalArgumentException() );
Ответ 4
С помощью java 8 lambda вы можете сделать:
myMock.doSomething(Mockito.any(String.class)).thenAnswer(invocation -> {
Object arg = invocation.getArguments()[0];
if ("1".equals(arg)) {
return "1";
}
throw new IllegalArgumentException("Expected 1 but got " + arg);
});
Ответ 5
Способ, описанный принятым ответом @Charlie, не работает (больше).
Когда вы пытаетесь переопределить общее поведение исключения исключения для какого-либо аргумента, первое правило запускается, и у вас есть исключение (как вы и просили).
Mockito.when(myMock.doSomething(any()))
.thenThrow(IllegalArgumentException.class);
Mockito.when(myMock.doSomething(eq("1"))).thenReturn("1"); //An exception is thrown here
// because of the call to .doSomething() on the mock object
Чтобы избежать этого вызова, можно использовать метод Mockito.doReturn()
:
Mockito.when(myMock.doSomething(any()))
.thenThrow(IllegalArgumentException.class);
Mockito.doReturn("1").when(myMock).doSomething(eq("1"));
Исходная проблема является одной из причин, по которой doReturn()
существует в соответствии с этим javadoc:
Here are those rare occasions when doReturn() comes handy:
<...some lines are skipped...>
Overriding a previous exception-stubbing:
hen(mock.foo()).thenThrow(new RuntimeException());
//Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
when(mock.foo()).thenReturn("bar");
//You have to use doReturn() for stubbing:
doReturn("bar").when(mock).foo();
Ответ 6
В качестве альтернативы вы можете использовать проверку, как показано ниже:
when(myMock.doSomething("1")).thenReturn( "1" );
assertEquals(myMock.doSomething("1"),"1");
verify(myMock).doSomething("1")