How does Mockito handle overlapping matchers with multiple arguments in the thenReturn block

后端 未结 3 2660
醉梦人生
醉梦人生 2021-02-20 17:52

I\'ve got a block of test code that is attempting to, in the generic case return two values on subsequent calls, but in specific cases only return the value associated with that

3条回答
  •  梦谈多话
    2021-02-20 18:16

    One way to workaround this problem could be to use a regular expression to avoid overlapping as next:

    when(mockObject.method(eq("expectedInput1"))).thenReturn(string1);
    when(mockObject.method(eq("expectedInput2"))).thenReturn(string2);
    // Match with any input string that doesn't contain expectedInput1 neither expectedInput2
    when(mockObject.method(matches("((?!expectedInput1|expectedInput2).)*")))
        .thenReturn(string1, string2);
    

    Example:

    System.out.println("expectedInput1=" + mockObject.method("expectedInput1"));
    System.out.println("expectedInput2=" + mockObject.method("expectedInput2"));
    System.out.println("foo=" + mockObject.method("foo"));
    System.out.println("bar=" + mockObject.method("bar"));
    System.out.println("bar=" + mockObject.method("bar"));
    

    Output:

    expectedInput1=string1
    expectedInput2=string2
    foo=string1
    bar=string2
    bar=string2
    

    Another way could be to implement your ArgumentMatcher still to avoid overlapping:

    when(mockObject.method(eq("expectedInput1"))).thenReturn(string1);
    when(mockObject.method(eq("expectedInput2"))).thenReturn(string2);
    when(
        mockObject.method(
            argThat(
                new ArgumentMatcher(){
                    @Override
                    public boolean matches(final Object argument) {
                        return !"expectedInput1".equals(argument) 
                            && !"expectedInput2".equals(argument);
                    }
                }
            )
        )
    ).thenReturn(string1, string2);
    

    Another way could be to implement your Answer with something like this:

    when(mockObject.method(anyString())).thenAnswer(
        new Answer() {
            Iterator it = Arrays.asList(string1, string2).iterator();
            String result;
            @Override
            public String answer(final InvocationOnMock invocation) throws Throwable {
                String argument = (String) invocation.getArguments()[0];
                switch (argument) {
                    case "expectedInput1" :
                        return string1;
                    case "expectedInput2" :
                        return string2;
                    default:
                        if (it.hasNext()) {
                            result = it.next();
                        }
                        return result;
                }
            }
        }
    );
    

提交回复
热议问题