Reputation: 2733
I like to do something like the following:
.when(
myMock.doSomething(
Matchers.eq( "1" )
)
)
.thenReturn( "1" )
.othwerwise()
.thenThrow( new IllegalArgumentException() );
Of course otherwise()
method doesn't exist but just to show you what I want to accomplish.
Upvotes: 27
Views: 16486
Reputation: 834
The way described by the accepted answer by @Charlie doesn't work (anymore). When you try to override the general throw exception behaviour for some argument the first rule is triggered and you have an exception (just as you asked).
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
To avoid that call one can use Mockito.doReturn()
method:
Mockito.when(myMock.doSomething(any()))
.thenThrow(IllegalArgumentException.class);
Mockito.doReturn("1").when(myMock).doSomething(eq("1"));
The initial issue is one of reasons why doReturn()
exists according to it's 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();
Upvotes: 3
Reputation: 4451
With java 8 lambda you can do:
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);
});
Upvotes: 1
Reputation: 3428
Alternatively you can use verify, as follows:
when(myMock.doSomething("1")).thenReturn( "1" );
assertEquals(myMock.doSomething("1"),"1");
verify(myMock).doSomething("1")
Upvotes: -1
Reputation: 7349
(Slight disclaimer, I've never done this personally, just read about it in the javadoc)... If all of your methods on your mock interface would be ok with the same default behaviour, you could set the default answer on your mock in a manner like:
Foo myMock = Mockito.mock(Foo.class,new ThrowsExceptionClass(IllegalArgumentException.class));
Mockito.when(myMock.doSomething(Matchers.eq("1"))).thenReturn("1");
JavaDoc Links for: Mockito#mock and ThrowsExceptionClass
Alternatively, as is discussed in the Stubbing tutorial, order of the stubbing matters and last matching wins, so you might be able to also do:
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");
Upvotes: 27
Reputation: 11805
you could create your own Answer implementation which would pay attention to the called parameters:
myMock.doSomething(Mockito.any(String.class)).thenAnswer( myAnswer );
The implementation of said answer could do something like this:
public String answer(InvocationOnMock invocation) {
if ("1".equals(invocation.getArguments()[0])) {
return "1";
}
else {
throw new IllegalArgumentException();
}
}
Upvotes: 10
Reputation: 34367
Just use opposite condition i.e. consider your example itself. You may want to use not(eq())
when you need otherwise
:
.when( myMock.doSomething(Matchers.eq( "1" )))
.thenReturn( "1" )
.when( myMock.doSomething(not(Matchers.eq( "1" ))))
.thenThrow( new IllegalArgumentException() );
Upvotes: 5