Mockito 3 Stubber doReturn

Mockito doReturn() is equivalent to Mockito when, it is used to stub the void method.

Mockito#when recommended over Mockito#doReturn for stubbing especially when stubbing consecutive calls because it is argument type-safe and more readable.

package com.example.mokito3.sujan;

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

import org.junit.jupiter.api.Assertions;
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.Mockito.doReturn;
import static org.mockito.Mockito.mock;

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

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class);
        doReturn("i eat apple").when(appleService).processApple("Macintosh");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat apple", apple);
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        doReturn("i eat apple").when(appleService).processApple("Macintosh");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat 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()
}

 

Stubber doReturn Continues stub

doReturn method has overloaded constructor which allows to configure continues stub.

package com.example.mokito3.sujan;

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

import org.junit.jupiter.api.Assertions;
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.Mockito.doReturn;
import static org.mockito.Mockito.mock;

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

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class);
        doReturn("i eat apple", "i have apple").when(appleService).processApple("Macintosh");
        String appleCase1 = appleService.processApple("Macintosh");
        String appleCase2 = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat apple", appleCase1);
        Assertions.assertEquals("i have apple", appleCase2);
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        doReturn("i eat apple", "i have apple").when(appleService).processApple("Macintosh");
        String appleCase1 = appleService.processApple("Macintosh");
        String appleCase2 = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat apple", appleCase1);
        Assertions.assertEquals("i have apple", appleCase2);
    }
}
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()
}

 

Overriding Exception Stub

Although not recomemded but there might be a scnerio to override privious stub. In normal stubbing override stub will take over except exception stub.

These scnerio is very rare and should not occur, overriding stubbing is a code smell and must be avoided at any cost.

package com.example.mokito3.sujan;

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

import org.junit.jupiter.api.Assertions;
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.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")).thenThrow(new RuntimeException("exception will be thrown"));
        when(appleService.processApple("Macintosh")).thenReturn("i eat apple");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat apple", apple);
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException("exception will be thrown"));
        when(appleService.processApple("Macintosh")).thenReturn("i eat apple");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat 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()
}

To correctly override exception stub doReturn method must be used and to avoid UnnecessaryStubbingException because of multiple stubbing for same input parameter Strictness#LENIENT must be configured.

package com.example.mokito3.sujan;

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

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@MockitoSettings(strictness = Strictness.LENIENT)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleWithStaticMockTest() {
        AppleService appleService = mock(AppleService.class);
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException("exception will be thrown"));
        doReturn("i eat apple").when(appleService).processApple("Macintosh");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat apple", apple);
    }

    @Test
    void saveAppleWithAnnotationMockTest() {
        when(appleService.processApple("Macintosh")).thenThrow(new RuntimeException("exception will be thrown"));
        doReturn("i eat apple").when(appleService).processApple("Macintosh");
        String apple = appleService.processApple("Macintosh");
        Assertions.assertEquals("i eat 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()
}

Spy side effects

Spy calls the real method, but calling a real method on spy brings its side effects.

in below example a spy of LinkedList has been created, so appleList#get(0) will actuly call the real method, but because LinkedList is still empty so IndexOutOfBoundsException will be thrown.

package com.example.mokito3.sujan;

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

import java.util.LinkedList;
import java.util.List;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {

    @Test
    void saveAppleWithStaticMockTest() {
        List<String> appleList = spy(LinkedList.class);
        when(appleList.get(0)).thenReturn("Macintosh");
        String apple = appleList.get(0);
        Assertions.assertEquals("Macintosh", apple);
    }
}

to properly avoid side effect of calling a real method on spy use doReturn.

package com.example.mokito3.sujan;

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

import java.util.LinkedList;
import java.util.List;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {

    @Test
    void saveAppleWithStaticMockTest() {
        List<String> appleList = spy(LinkedList.class);
        doReturn("Macintosh").when(appleList).get(0);
        String apple = appleList.get(0);
        Assertions.assertEquals("Macintosh", apple);
    }
}

follow us on