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());
}
}