Explain Codes LogoExplain Codes Logo

Mockito verify order / sequence of method calls

java
mockito
testing-strategies
unit-testing
Alex KataevbyAlex Kataev·Oct 13, 2024
TLDR

To assert the sequence of method calls, use Mockito's InOrder:

// Mocking the class MyClass mockObject = Mockito.mock(MyClass.class); // Having a blast with method calls mockObject.methodOne(); mockObject.methodTwo(); // Time to play Sherlock Holmes on sequence verification InOrder inOrder = Mockito.inOrder(mockObject); inOrder.verify(mockObject).methodOne(); // Elementary, my dear Watson! Called first. inOrder.verify(mockObject).methodTwo(); // Surely, followed by this!

In this magic trick, InOrder makes darn sure methodOne shows up before methodTwo.

Creating and using mock objects

1. Creating mock objects

Your voyage to sequence verification begins with mock objects:

ServiceClassA serviceA = Mockito.mock(ServiceClassA.class); ServiceClassB serviceB = Mockito.mock(ServiceClassB.class);

When you wish to perform a "mum's the word" act on void methods, rely on Mockito.doNothing().when():

Mockito.doNothing().when(serviceA).performAction(); // Look Ma, No exceptions!

2. Playing with sequence

It's time to call upon the Mockito Order Police - InOrder:

InOrder inOrder = Mockito.inOrder(serviceA, serviceB); // Get your ducks in a row!

Now, romancing the sequence:

inOrder.verify(serviceA).performAction(); // Quick step inOrder.verify(serviceB).anotherAction(); // Waltz

Life is a dance, but so can be behavior verification. Behold BDD:

import static org.mockito.BDDMockito.*; given(serviceA).willDoNothing(); // It's doing nothing. Literally nothing. then(inOrder).should(serviceA).performAction(); then(inOrder).should(serviceB).anotherAction();

3. Playing with arguments

Handling specific arguments with grace:

inOrder.verify(serviceA).processData(any(DataType.class)); // I like 'em unspecified. inOrder.verify(serviceB).processData(eq(specificArgument)); // But sometimes, specifics aren't too bad.

Stay focused on the sequence of method calls in your tests - after all, order matters!

Bleeding edge testing strategies

1. Structuring for clarity

In Kotlin, you can make your tests cleaner and more human-readable:

val mockService: Service = mock() WHEN(mockService).process(isA<Request>()) // WHEN service processes shouldn't mean "if" THEN(mockService).should(times(1)).reply(isA<Response>()) // THEN it should reply exactly once - not thrice, twice isn't nice.

2. Zooming in on method specifics

To spot the specific actions, grab your trusty binoculars:

inOrder.verify(serviceA).updateDatabase(withCustomerData(customer)); // Look! It's updating the database!

Test like a pro - give importance to event names and their order.

3. Using private variables

For uncomplicated test setup, private variables are your best pals:

private ServiceClassA serviceA = mock(ServiceClassA.class); // team A private ServiceClassB serviceB = mock(ServiceClassB.class); // team B

With these variables, you can cook up scenarios foxier than James Bond.

4. Tackling complex scenarios

With a multitude of methods, strap on an army of verify().invoke():

inOrder.verify(serviceA).stepOne(); // One small step for code inOrder.verify(serviceB).stepTwo(); // One giant leap for codekind inOrder.verify(serviceA).stepThree(); // And the saga continues // and so it goes...

Test smart. Your goal is to understand how your methods interact in the wild.