Mockito 3 InOrder

Mockito#verify provides us a great way to validate the mock instance call with the desired parameter and its response, but what if we not only want to validate the request and response of mock instance but the order of invocation as well. For this Mockito Provides us InOrder interface.

package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class);
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.saveApple("Fuji");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).saveApple("Fuji");
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.saveApple("Fuji");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).saveApple("Fuji");
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

InOrder with VerificationMode

We need to verify the order of interaction with the mock instance, but we have the same method call with the same parameter, one way is to use multiple InOrder#verify method, or the better way is to use VerificationMode#times.

All the methods of VerificationMode#times can be used with InOrder#verify.

  • times(count)
  • never()
  • atLeastOnce()
  • atLeast(count)
  • atMost(count)
  • only
package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService saveAppleService;

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService saveAppleService = mock(AppleService.class);
        InOrder inOrder = inOrder(saveAppleService);
        saveAppleService.saveApple("Macintosh");
        saveAppleService.saveApple("Macintosh");
        inOrder.verify(saveAppleService, times(2)).saveApple("Macintosh");
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        InOrder inOrder = inOrder(saveAppleService);
        saveAppleService.saveApple("Macintosh");
        saveAppleService.saveApple("Macintosh");
        inOrder.verify(saveAppleService, times(2)).saveApple("Macintosh");
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

InOrder for multiple method

A mock instance will have multiple methods, we can use Inorder interface to validate multiple interactions with the mock instance for multiple methods as well.

package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }

    public String getApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class);
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).getApple("Macintosh");
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).getApple("Macintosh");
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

InOrder Short Hand Notation

Inorder is very flexible in terms of validating orders of mock instance interaction. It can be used with multiple classes as well, but creating multiple Inorder instances of mock objects will be boilerplate code, to avoid this, Instance interface support shorthand notation as well. we can pass multiple mock instances in inorder at a time.

package com.example.mokito3.sujan;

public class GetAppleService {
    public String getApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

public class SaveAppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private SaveAppleService saveAppleService;
    @Mock
    private GetAppleService getAppleService;

    @Test
    void saveAppleWithStaticMockTest() {
        SaveAppleService saveAppleService = mock(SaveAppleService.class);
        GetAppleService getAppleService = mock(GetAppleService.class);
        InOrder inOrder = inOrder(saveAppleService, getAppleService);
        saveAppleService.saveApple("Macintosh");
        getAppleService.getApple("Macintosh");
        inOrder.verify(saveAppleService).saveApple("Macintosh");
        inOrder.verify(getAppleService).getApple("Macintosh");
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        InOrder inOrder = inOrder(saveAppleService, getAppleService);
        saveAppleService.saveApple("Macintosh");
        getAppleService.getApple("Macintosh");
        inOrder.verify(saveAppleService).saveApple("Macintosh");
        inOrder.verify(getAppleService).getApple("Macintosh");
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

InOrder VerifyNoMoreInteractions

InOrder verifies the order of interaction and execution of the mock instance. Once all interactions have been verified, InOrder provides us InOrder#verifyNoMoreInteractions to make sure that there is no more interaction with the mock instance.

verifies if mocks have any unverified interaction.

InOrder#verifyNoMoreInteractions  is used after all verifications to make sure that nothing else was invoked on mocks.

package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }

    public String getApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void inOrderVerifyNoMoreInteractions() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).getApple("Macintosh");
        inOrder.verifyNoMoreInteractions();
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

its not recomeneded to use verifyNoMoreInteractions in every test method. Use only when it's relevant. Abusing will leads to overspecified, less maintainable tests.

InOrder#verifyNoMoreInteractions vs Mockito#verifyNoMoreInteractions

Mockito provides Mockito#verifyNoMoreInteractions and Inorder also provides InOrder#verifyNoMoreInteractions method to validate that there is no more interaction with the mock intance, but there is significant difference between them.

InOrder#verifyNoMoreInteractions is different then Mockito#verifyNoMoreInteractions

package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }

    public String getApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void inOrderVerifyNoMoreInteractions() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verify(appleService).getApple("Macintosh");
        inOrder.verifyNoMoreInteractions();
    }

    @Test
    void mockitoVerifyNoMoreInteractions() {
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        Mockito.verify(appleService).saveApple("Macintosh");
        Mockito.verify(appleService).getApple("Macintosh");
        Mockito.verifyNoMoreInteractions(appleService);
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

Mockito#verifyNoMoreInteractions is make sure that all the interactions are verified which can be in any order where as inOrder#verifyNoMoreInteractions make sure that interactions and order of inteactions both must be in order.

package com.example.mokito3.sujan;

public class AppleService {
    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }

    public String getApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.inOrder;


@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void inOrderVerifyNoMoreInteractions() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        inOrder.verify(appleService).getApple("Macintosh");
        inOrder.verify(appleService).saveApple("Macintosh");
        inOrder.verifyNoMoreInteractions();
    }

    @Test
    void mockitoVerifyNoMoreInteractions() {
        appleService.saveApple("Macintosh");
        appleService.getApple("Macintosh");
        Mockito.verify(appleService).getApple("Macintosh");
        Mockito.verify(appleService).saveApple("Macintosh");
        Mockito.verifyNoMoreInteractions(appleService);
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

 

follow us on