Как обрабатывать непревзойденные параметры в Mockito? - программирование
Подтвердить что ты не робот

Как обрабатывать непревзойденные параметры в Mockito?

Мне нравится делать что-то вроде следующего:

.when( 
    myMock.doSomething(
        Matchers.eq( "1" )
    ) 
)
.thenReturn( "1" )
.othwerwise()
.thenThrow( new IllegalArgumentException() );

Конечно, метод otherwise() не существует, а просто для того, чтобы показать вам, чего я хочу достичь.

4b9b3361

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