Table of Contents
In this lesson with Mockito, we will learn what is at the core of Mockito, which surprisingly is, mocks!
Mock is an object that has predefined answers to method executions made during the test and has recorded expectations of these executions.
Steps for creating Mockito TestNG example.
Step 1: Create a simple java maven project.
Adding to classpath, using Maven
Step 2: The fastest way to add Mockito to your project is using Maven dependency.
1 2 3 4 5 6 7 8 |
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all --> <dependency> Â Â Â <groupId>org.mockito</groupId> Â Â Â <artifactId>mockito-all</artifactId> Â Â Â <version>1.9.5</version> </dependency> |
This dependency is simple enough and does not bring any additional or redundant libraries. See here for latest versions of the library.
As we will also be using some JUnit functionality, we will also need it’s dependency. Let’s add it next,
1 2 3 4 5 6 7 8 |
<!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> Â Â Â <groupId>junit</groupId> Â Â Â <artifactId>junit</artifactId> Â Â Â <version>4.11</version> </dependency> |
Your pom.xml will look as below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<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>org.arpit.java2blog</groupId> <artifactId>MockitoMockExample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.9.5</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> </dependencies> </project> |
Creating a Mock
A mock needs to be created before it is actually used, just like anything else. We can use the mock() method in four separate ways to create a mock.
- mock(Class<T> classBeingMocked): This method creates a mock of a given class with a default answer set to returning default values. This is the most used method in tests.
- mock(Class<T>Â classBeingMocked, String name): This method creates a mock of a given class with a default answer set to returning default values. It also sets a name to the mock. This name is present in all verification messages. That’s very useful in debugging, since it allows you to distinguish the mocks.
- mock(Class<T>Â classBeingMocked, Answer defaultAnswer): This method creates a mock of a given class. In other words, all of the nonstubbed mock’s method will act as defined in the passed answer.
- mock(Class<T>Â classBeingMocked, MockSettings mockSettings): This method creates a mock of a given class with customizable mock settings. You should hardly ever need to use that feature.
Using mock()
Step 3: Let’s say you have a Customer class and you want to test calculate bill method of customer class. Bill calculation will depend on list of items customer purchased. We will use Mockito’s mock method to actually mock the items and add to the list.
In this way, we will be able to test calculate bill method without actually adding real items to listOfItems.
Let’s create a Customer class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package org.arpit.java2blog.mockito; import java.util.List; public class Customer { String name; List<Item> listOfItems; public int calculateBill() { int total = 0; for (Item item:listOfItems) { total+=item.getPrice(item.getName()); } return total; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Item> getListOfItems() { return listOfItems; } public void setListOfItems(List<Item> listOfItems) { this.listOfItems = listOfItems; } } |
Create an interface named Item as below.
1 2 3 4 5 6 7 |
package org.arpit.java2blog.mockito; public interface Item { String getName(); int getPrice(String name); } |
Now let’s create a test class which will actually test customer’s calculateBill method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package org.arpit.java2blog.test; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import org.arpit.java2blog.mockito.Customer; import org.arpit.java2blog.mockito.Item; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class CustomerBillTest { Customer c1; @Before public void setup(){ c1=new Customer(); c1.setName("John"); List<Item> listOfItems=new ArrayList<Item>(); Item i1=Mockito.mock(Item.class); Item i2=Mockito.mock(Item.class); Item i3=Mockito.mock(Item.class); listOfItems.add(i1); listOfItems.add(i2); listOfItems.add(i3); c1.setListOfItems(listOfItems); when(i1.getName()).thenReturn("Rice"); when(i2.getName()).thenReturn("Tea"); when(i3.getName()).thenReturn("Wheat"); when(i1.getPrice("Rice")).thenReturn(100); when(i2.getPrice("Tea")).thenReturn(200); when(i3.getPrice("Wheat")).thenReturn(300); } @Test public void test_Customer_CalculateBill() { int billAmount=c1.calculateBill(); Assert.assertEquals(600, billAmount); } } |
We have mocked Item i1,i2 and i3 here and used Mockito’s when,thenReturn method to mock behaviour in case getName and getPrice method getCalled.
Step 4: When you run the program, you will get below output:
Another example
Code that instantiates objects using the new keyword directly makes testing difficult. By using the Factory pattern you move the creation of the object outside of the code to be tested. This gives you a place to inject a mock object and/or mock factory.
We start by creating a testable Foo class and FooFactory implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class Foo { private int a; private int b; //public getters and setters } public interface FooFactory { public Foo create(int x, int y); } public class FoofactoryImpl implements Foofactory { public Foo create(int x, int y) { Foo foo = new Foo(); foo.setA(x); foo.setB(y); return foo; } } |
Now, our test class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class MyClass { private final FooFactory fooFactory; public MyClass(FooFactory fooFactory) { this.fooFactory = fooFactory; } public void doSomething() { Foo foo = fooFactory.create(100, 101); // do something with the foo ... } } |
Now you can pass in a mock factory in the test that will create a mock Foo or a Foo of your choosing. Let’s use Mockito to create the mock factory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class MyClassTest { @Test public void doSomething() { Foo foo = mock(Foo.class); // set expectations for foo ... FooFactory fooFactory = mock(FooFactory.class); when(fooFactory.create(100, 101)).thenReturn(foo); MyClass fixture = new MyClass(fooFactory); fixture.doSomething(); // make assertions ... } } |
Note: Now, the factory that instantiates Foo must be able to access the constructor, so, it should not be made private.
What are answers? When to use them?
In our examples above, we used thenReturn(…) because we simply wanted to return a mocked object i.e., Foo. But what if we want to do some processing based on the parameters passed to the method, create(100, 101) in our case.
thenAnswer() vs thenReturn()
Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
Simplest example to use a parameter which was passed to when(…) is to return it. This can only be done using thenAnswer(…).
1 2 3 4 5 6 7 8 9 |
when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); return fooFactory.create(args[1], args[0]); } }); |
In above example, we get the parameters and just use it in creating a Foo instance using factory method after swapping them.
Mocking with Annotation with different default answers
Usually, you won’t ever need to create a custom answer for Mockito, there are plenty of them already bundled in Mockito and there is no need to reinvent the wheel. Why would you want to create a custom answer anyway? Let’s take a look at a couple of possible answers to that point:
- It is probable that for debugging the app, you would like to log the arguments that were passed to the stubbed method.
- You want to perform some business logic on the passed argument rather than just return some fixed value.
- You want to stub asynchronous methods that have callbacks.
If you thought it over and still want to create a custom answer, please check if there isn’t one already existing in Mockito.
In the provided Mockito API, you can find the following answers in the AdditionalAnswers class (check the Javadoc of that class for examples):
- returnsFirstArg: This answer will return the first argument of the invocation
- returnsSecondArg: This answer returns the second argument of the invocation
- returnsLastArg: This answer returns the last argument of the invocation
- returnsArgAt: This answer returns the argument of the invocation provided at the given index
- delegatesTo: This answer delegates all methods to the delegate (you will, in fact, call the delegate’s method if the method hasn’t already been stubbed)
returnsElementsOf: This answer returns the elements of the provided collection.