Timo
Timo

Reputation: 2242

What happens when I use multiple whens for a mock?

public class TestClass {
    @Mock
    private SomeObject someObject;

    @InjectMocks
    private SubjectOfTesting subject;

    @Before
    public void setupMock() {
         when(someObject.doSomething(eq("Meh")).thenReturn("Boing");
         when(someObject.doSomething(eq("Foo")).thenReturn("Bar");
         when(someObject.doSomething(any()).thenReturn("?!"); // <-- This any()
    }

    @Test
    public void testSomethings() {
        subject.setArgument("Meh");
        String result = subject.useSomeObject();
        assertEquals("result is not equal", "Boing", result);
    }

    // Multiple tests with other arguments.
}

Given the class above, can I use the any() as well as the others? Will it perform as I expect, returning "Boing" or "Bar" or "?!" depending on the argument I provide in my test?

EDIT

Tested it with:

@RunWith(MockitoJUnitRunner.class)
public class TempTest {

    @Mock
    private SomeObject someObject;

    @InjectMocks
    private Subject subject = new Subject();

    @Before
    public void setupMock() {
        when(someObject.doSomething(eq("Meh"))).thenReturn("Boing");
        when(someObject.doSomething(eq("Foo"))).thenReturn("Bar");
        when(someObject.doSomething(any())).thenReturn("?!"); // <-- This any()
    }

    @Test
    public void testSomethingsMeh() {
        subject.setArgument("Meh");
        String result = subject.useSomeObject();
        assertEquals("result is not equal", "Boing", result);
    }

    @Test
    public void testSomethingsFoo() {
        subject.setArgument("Foo");
        String result = subject.useSomeObject();
        assertEquals("result is not equal", "Bar", result);
    }

    @Test
    public void testSomethingsAny() {
        subject.setArgument("Any");
        String result = subject.useSomeObject();
        assertEquals("result is not equal", "?!", result);
    }

    private interface SomeObject {
        String doSomething(String argument);
    }

    private class Subject {
        private SomeObject someObject;
        private String argument;

        public Subject() {
        }

        public void setSomeObject(final SomeObject someObject) {
            this.someObject = someObject;
        }

        public String useSomeObject() {
            return this.someObject.doSomething(this.argument);
        }

        public void setArgument(final String argument) {
            this.argument = argument;
        }
    }
}

Results in (two failures, the other passes):

org.junit.ComparisonFailure: result is not equal expected:<[Bar]> but was:<[?!]>
org.junit.ComparisonFailure: result is not equal expected:<[Boing]> but was:<[?!]>

Is there a way make these tests pass?

Upvotes: 1

Views: 70

Answers (1)

Sergii Bishyr
Sergii Bishyr

Reputation: 8641

The last when will override all pervious. But you can achieve the results you need if you change the order of stubbing. This will work as you expect.

when(someObject.doSomething(any()).thenReturn("?!"); 
when(someObject.doSomething(eq("Meh")).thenReturn("Boing");
when(someObject.doSomething(eq("Foo")).thenReturn("Bar");

Upvotes: 1

Related Questions