68

I am trying to create a mock for a call. Say I have this method I am trying to stub out:

class ClassA {
  public String getString(String a) {
    return a + "hey";
  }
}

What I am trying to mock out is: 1st instance is

when(classA.getString(eq("a")).thenReturn(...);`

in the same test case

when(classA.getString([anything that is not a])).thenReturn(somethingelse);

The 2nd case is my question: How do I match anyString() other than "a"?

Enumy
  • 841
  • 2
  • 8
  • 20
Churk
  • 4,556
  • 5
  • 22
  • 37

4 Answers4

135

With Mockito framework, you can use AdditionalMatchers

ClassA classA = Mockito.mock(ClassA.class);
Mockito.when(classA.getString(Matchers.eq("a"))).thenReturn("something"); 
Mockito.when(classA.getString(AdditionalMatchers.not(Matchers.eq("a")))).thenReturn("something else");

Hope it helps.

troig
  • 7,072
  • 4
  • 37
  • 63
  • 1
    AdditionalMatchers seems to removed by now. – Pieter De Bie Jul 09 '18 at 11:12
  • 2
    Hi @PieterDeBie I think AdditionalMatchers is still in the current Mockito version. [See it on the github project](https://github.com/mockito/mockito/blob/release/2.x/src/main/java/org/mockito/AdditionalMatchers.java) – troig Oct 19 '18 at 13:50
  • 1
    As Matchers is deprecated, use ArgumentMatchers instead. See also here: https://zgrepcode.com/mockito/2.24.8/org/mockito/matchers.java – GedankenNebel Apr 16 '19 at 11:41
  • 2
    There is a notable caveat here though. The return type of AdditionalMatchers::not is 0 for all numeric primitives, false for the boolean primitive and *null* for all non primitive objects T. This means that you will run into ugly warnings when you try to use it on mocked methods where the parameters are annotated with @Nonnull. – Daniel W. Nov 26 '19 at 13:11
10

Use argThat with Hamcrest:

when(classA.getString(argThat(CoreMatchers.not(CoreMatchers.equalTo("a")))...

You might also be able to do this via ordering. If you put one when(anyString) and when(eq("a")) in the correct order, Mockito should test them in order and do the "a" logic when appropriate and then "anyString" logic otherwise.

John B
  • 32,493
  • 6
  • 77
  • 98
8

In mockito the last stubbing is the most important. This means that you can simply use the standard matchers for your needs:

// "Default" return values.
when(classA.getString(ArgumentMatchers.anyString())).thenReturn(somethingelse);
// Specific return value for "a"
when(classA.getString(ArgumentMatchers.eq("a"))).thenReturn(something);

Note that you have to use ArgumentMatchers for both since you're mixing them.

Pieter De Bie
  • 1,074
  • 13
  • 30
1

I actually took this approach after carefully looking at the suggested answers:

doAnswer(new Answer<String>() {
  public String answer(InvocationOnMock invocation) throws Throwable {
    String originalParam = (String) invocation.getArguments()[0];
    return StringUtils.equalsIgnoreCase(originalParam, "a") ? "Something" : "Something Else";
  }
}).when(classA).getString(anyString());

This allows me to handle more than just two cases by adjusting the return base on the params.

Churk
  • 4,556
  • 5
  • 22
  • 37
  • 2
    This is a good solution but I think both mine and @John B anwers are closer to your OP requeriments. – troig Jul 10 '15 at 15:45