MOCKITO – MOCK vs. SPY and WHEN vs. DORETURN

If you mock a method for a unit test the actual method is not invoked, but what about you want to call the actual method but just mock the return value?

Mockito gives you the @Spy for “partial mocking, real methods are invoked but still can be verified and stubbed” [1] which is perfect, but what if you want to invoke the actual method for one of the methods from the spied object and just manipulate the return value, but also do not want to call the actual implementation for another one from the exact same spied object and just need the manipulated return value. Luckily, Mockito gives you another two options [2]:

  • when(...) thenReturn(...) makes a real method call.
  • doReturn(...) when(...) does not call the method at all.

Let’s see how it works:

public class MyClass {
private MyDatabase myDatabase;
public String getCustomerName(long customerNo) {
System.out.println("getCustomerName() is called!");
return myDatabase.query(customerNo)+"_FROM_DATABASE";
}
public MyDatabase getMyDatabase() {
return myDatabase;
}
public void setMyDatabase(MyDatabase myDatabase) {
this.myDatabase = myDatabase;
}
}
view raw MyClass.java hosted with ❤ by GitHub
import static org.mockito.Matchers.anyLong;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import com.MyClass;
import com.MyDatabase;
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@BeforeClass
public static void beforeClass() {
System.out.println("Tests are going to start now!");
}
@Before
public void before() {
System.out.println("******************************");
System.out.println("");
}
@After
public void after() {
System.out.println("");
}
@Test
public void testMockWithWhen() {
System.out.println("---testMockWithWhen started---");
MyClass mockedClass = mock(MyClass.class);
when(mockedClass.getCustomerName(anyLong())).thenReturn("John");
String actualCustomerName = mockedClass.getCustomerName(1000);
String expectedCustomerName = "John";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testMockWithWhen finished---");
};
@Test
public void testMockWithDoReturn() {
System.out.println("---testMockWithDoReturn started---");
MyClass mockedClass = mock(MyClass.class);
doReturn("John").when(mockedClass).getCustomerName(anyLong());
String actualCustomerName = mockedClass.getCustomerName(1000);
String expectedCustomerName = "John";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testMockWithDoReturn finished---");
};
@Test
public void testSpyWithWhen() {
System.out.println("---testSpyWithWhen started---");
MyClass mockedClass = spy(MyClass.class);
mockedClass.setMyDatabase(new MyDatabase());
when(mockedClass.getCustomerName(anyLong())).thenReturn("John");
String actualCustomerName = mockedClass.getCustomerName(1000);
String expectedCustomerName = "John";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testSpyWithWhen finished---");
};
@Test
public void testSpyWithDoReturn() {
System.out.println("---testSpyWithDoReturn started---");
MyClass mockedClass = spy(MyClass.class);
// not necessary this time mockedClass.setMyDatabase(new MyDatabase());
doReturn("John").when(mockedClass).getCustomerName(anyLong());
String actualCustomerName = mockedClass.getCustomerName(1000);
String expectedCustomerName = "John";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testSpyWithDoReturn finished---");
};
@Test
public void testMockDependencyWithWhen() {
System.out.println("---testMockDependencyWithWhen started---");
MyDatabase mockedDatabase = mock(MyDatabase.class);
when(mockedDatabase.query(anyLong())).thenReturn("John");
MyClass myClass = new MyClass();
myClass.setMyDatabase(mockedDatabase);
String actualCustomerName = myClass.getCustomerName(1000);
/** IMPORTANT **/
String expectedCustomerName = "John_FROM_DATABASE";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testMockDependencyWithWhen finished---");
};
@Test
public void testMockDependencyWithDoReturn() {
System.out.println("---testMockDependencyWithDoReturn started---");
MyDatabase mockedDatabase = mock(MyDatabase.class);
doReturn("John").when(mockedDatabase).query(anyLong());
MyClass myClass = new MyClass();
myClass.setMyDatabase(mockedDatabase);
String actualCustomerName = myClass.getCustomerName(1000);
/** IMPORTANT **/
String expectedCustomerName = "John_FROM_DATABASE";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testMockDependencyWithDoReturn finished---");
};
@Test
public void testSpyDependencyWithWhen() {
System.out.println("---testSpyDependencyWithWhen started---");
MyDatabase mockedDatabase = spy(new MyDatabase());
when(mockedDatabase.query(anyLong())).thenReturn("John");
MyClass myClass = new MyClass();
myClass.setMyDatabase(mockedDatabase);
String actualCustomerName = myClass.getCustomerName(1000);
/** IMPORTANT **/
String expectedCustomerName = "John_FROM_DATABASE";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testSpyDependencyWithWhen finished---");
};
@Test
public void testSpyDependencyWithDoReturn() {
System.out.println("---testSpyDependencyWithDoReturn started---");
MyDatabase mockedDatabase = spy(new MyDatabase());
doReturn("John").when(mockedDatabase).query(anyLong());
MyClass myClass = new MyClass();
myClass.setMyDatabase(mockedDatabase);
String actualCustomerName = myClass.getCustomerName(1000);
/** IMPORTANT **/
String expectedCustomerName = "John_FROM_DATABASE";
assertEquals(expectedCustomerName, actualCustomerName);
System.out.println("---testSpyDependencyWithDoReturn finished---");
};
}
view raw MyClassTest.java hosted with ❤ by GitHub
public class MyDatabase {
public String query(long customerNo) {
// TODO implement
System.out.println("query() is called!");
return null;
}
}
view raw MyDatabase.java hosted with ❤ by GitHub
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>MockitoTutorial</groupId>
<artifactId>MockitoTutorial</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<powermock.version>1.7.1</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
view raw pom.xml hosted with ❤ by GitHub

Output:
Tests are going to start now!
******************************

—testMockWithDoReturn started—
—testMockWithDoReturn finished—

******************************

—testSpyWithDoReturn started—
—testSpyWithDoReturn finished—

******************************

—testMockDependencyWithDoReturn started—
getCustomerName() is called!
—testMockDependencyWithDoReturn finished—

******************************

—testSpyDependencyWithWhen started—
query() is called!
getCustomerName() is called!
—testSpyDependencyWithWhen finished—

******************************

—testMockDependencyWithWhen started—
getCustomerName() is called!
—testMockDependencyWithWhen finished—

******************************

—testSpyDependencyWithDoReturn started—
getCustomerName() is called!
—testSpyDependencyWithDoReturn finished—

******************************

—testMockWithWhen started—
—testMockWithWhen finished—

******************************

—testSpyWithWhen started—
getCustomerName() is called!
query() is called!
—testSpyWithWhen finished—

 

[1] https://site.mockito.org/

[2] https://stackoverflow.com/a/29394497/1091666

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: