freddens
freddens

Reputation: 13

Dynamic thenReturn()-Statements in Mockito

id like to have a method that can dynamically create Mock objects of a certain class.

static Scanner mockScanner(int personsEntering, int personsLeaving) {
        Scanner scanner = mock(Scanner.class);

        when(scanner.readyToProcessPerson()).thenReturn(true);

        when(scanner.personWantsToEnter()).thenReturn(true).thenReturn(true).thenReturn(false);
        return scanner;
}

The method personWantsToEnter() in Scanner returns true or false depending on wether a persons wants to enter or leave. I want my method mockScanner() return a mock-object that simulates persons entering and leaving depending on the parameters 'personsEntering' and 'personsLeaving'. (For example: when 'personsEntering' is 2 and 'personsLeaving' is 1, the mock-object should behave like it is shown in the code-example above.) Is there any possible way to do so?

Upvotes: 0

Views: 344

Answers (1)

Progman
Progman

Reputation: 19545

You can call thenReturn() dynamically within a for() loop, depending on the given arguments personsEntering and personsLeaving. Each time you have to update the OngoingStubbing<Boolean> variable you get from the when() method. Your code might look like this:

public static Foobar mockFoobar(int personsEntering, int personsLeaving) {
    Foobar f = Mockito.mock(Foobar.class);
    
    OngoingStubbing<Boolean> stub = Mockito.when(f.personWantsToEnter());
    
    for (int i=0; i<personsEntering; i++) {
        stub = stub.thenReturn(true);
    }
    for (int i=0; i<personsLeaving; i++) {
        stub = stub.thenReturn(false);
    }
    return f;
}

(I replaced Scanner with Foobar to avoid confusions with java.util.Scanner)

See the following unit test which will pass based on the given call of mockFoobar():

@Test
void test() throws Exception {
    Foobar test = mockFoobar(4, 2);
    Assertions.assertTrue(test.personWantsToEnter());
    Assertions.assertTrue(test.personWantsToEnter());
    Assertions.assertTrue(test.personWantsToEnter());
    Assertions.assertTrue(test.personWantsToEnter());
    Assertions.assertFalse(test.personWantsToEnter());
    Assertions.assertFalse(test.personWantsToEnter());
}

Upvotes: 1

Related Questions