supertonsky
supertonsky

Reputation: 2733

How do I handle unmatched parameters in Mockito?

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

Answers (6)

Dmitry P.
Dmitry P.

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

Thermech
Thermech

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

fairidox
fairidox

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

Charlie
Charlie

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

Matt
Matt

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

Yogendra Singh
Yogendra Singh

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

Related Questions