Mockito 3 Stubbing When

The stubbing feature in Mockito allows us to modify the behavior of mock objects and behave in a certain way under certain conditions. we can change the method processing way and response for a particular input. in simple terms, when the X method is called with Y as an input parameter then Z should be the output response.

The stub can be configured to return null, primitive, wrapper, or an empty collection as per requirement.

Mockito provides when static when method to stub methods

package com.example.mokito3.sujan;

import java.util.Objects;

public class AppleService {
    public String processApple(String appleName) {
        return "I love " + appleName + " Apple";
    }
}
package com.example.mokito3.sujan;

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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

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

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class); 
        when(appleService.processApple("Macintosh")).thenReturn("apple name is Macintosh");
        String appleName = appleService.processApple("Macintosh");
        assertEquals("apple name is Macintosh", appleName);
    }

    @Test
    void saveAppleWithAnnotationMockTest() { 
        when(appleService.processApple("Macintosh")).thenReturn("apple name is Macintosh");
        String appleName = appleService.processApple("Macintosh");
        assertEquals("apple name is Macintosh", appleName);
    }
}
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()
}

if we stub a method multiple times, the last stub overrides previous stubs.

Overridding stubbing is a potential code smell.

package com.example.mokito3.sujan;

    public class AppleService {
        public String processApple(String appleName) {
            return "I love Apple";
        }
}
package com.example.mokito3.sujan;

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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

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

    @Test
    void saveAppleWithMockTest() {
        when(appleService.processApple("Macintosh")).thenReturn("i eat macintosh apple");
        when(appleService.processApple("Macintosh")).thenReturn("i eat fuji apple");
        assertEquals("i eat fuji apple", appleService.processApple("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()
}

 

a mock instance method stubbed for a particular input parameter will always return stubbed output for the particular request, irrespective of the number of times called.

Once stubbed will always be stubbed.

package com.example.mokito3.sujan;

public class AppleService {
    public String processApple(String appleName) {
        String message = "i love " + appleName + " Apple";
        System.out.println("message = " + message);
        return message;
    }
}
package com.example.mokito3.sujan;

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

import java.util.stream.IntStream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

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

    @Test
    void saveAppleWithMockTest() {
        when(appleService.processApple("Macintosh")).thenReturn("i eat macintosh apple");
        IntStream.rangeClosed(1, 5).forEach(value -> {
            String apple = appleService.processApple("Macintosh");
            assertEquals("i eat macintosh apple", apple);
        });
    }
}
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 Consecutive Stubbing

Mokito provides us a way to stub the method X for Y as input then Z as output, but what if we want a different output with each iteration. Mockito supports continuous stubbing, ie we can stub method for a different response every time its called for the same input.

package com.example.mokito3.sujan;

public class AppleService {
    public String processApple(String appleName) {
        return "I love Apple";
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class AppleServiceTest {
    @Test
    void saveAppleWithMockTest() {
        AppleService appleService = mock(AppleService.class);
        when(appleService.processApple("Macintosh")).thenReturn("i eat macintosh apple").thenReturn("i eat fuji apple").thenReturn("i eat gala apple");
        assertEquals("i eat macintosh apple", appleService.processApple("Macintosh"));
        assertEquals("i eat fuji apple", appleService.processApple("Macintosh"));
        assertEquals("i eat gala apple", appleService.processApple("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()
}

 

Mockito Consecutive Stubbing Short Hand Notation

Mockito provides a shorthand notation of consecutive stubbing.

package com.example.mokito3.sujan;

public class AppleService {
    public String processApple(String appleName) {
        return "I love Apple";
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class AppleServiceTest {
    @Test
    void saveAppleWithMockTest() {
        AppleService appleService = mock(AppleService.class);
        when(appleService.processApple("Macintosh")).thenReturn("i eat macintosh apple", "i eat fuji apple", "i eat gala apple");
        assertEquals("i eat macintosh apple", appleService.processApple("Macintosh"));
        assertEquals("i eat fuji apple", appleService.processApple("Macintosh"));
        assertEquals("i eat gala apple", appleService.processApple("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()
}

Mockito One-liner stubs

In order to stub in the Mockito framework, we need a mock object, then with the help of when-then, we can assign the desired result. Mockito provides a way to create mock and stub in a single line and save redundant code.

package com.example.mokito3.sujan;

public class AppleService {
    public String processApple(String appleName) {
        return "I love " + appleName + " Apple";
    }
}
package com.example.mokito3.sujan;

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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = when(mock(AppleService.class).processApple("Macintosh")).thenReturn("apple name is Macintosh").getMock();
        String appleName = appleService.processApple("Macintosh");
        verify(appleService).processApple("Macintosh");
        assertEquals("apple name is Macintosh", appleName);
    }
}
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()
}

when method has a lot of overloaded constructors.

package com.example.mokito3.sujan;

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

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

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

    @Test
    void saveAppleMockTest() {
        /* stubbing a mock instance */
        when(appleService.processApple()).thenReturn("i eat macintosh apple");

        /* stubbing using argument matchers */
        when(appleService.processApple(anyString())).thenReturn("i eat macintosh apple");

        /* stubbing for exception */
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException());

        /*  continues stubbing */
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException()).thenReturn("foo");

        /*  continues stubbing short hand */
        when(appleService.processApple("Macintosh")).thenReturn("one", "two");

        /*  continues stubbing short hand alternate way */
        when(appleService.processApple("Macintosh")).thenReturn("one").thenReturn("two");

        /*  continues stubbing short hand with exception */
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException(), new NullPointerException());
    }
}

 

follow us on