Writing JUnit Test Cases Using Mockito
In this example we will learn how to write JUnit tests using Mockito. A unit test should test a class in isolation. Side effects from other classes or the system should be eliminated if possible. Mockito lets you write beautiful tests with a clean & simple API. Tools and technologies used in this example are Java 1.8, Eclipse Luna 4.4.2
1. Introduction
Mockito is a popular mocking framework which can be used in conjunction with JUnit. Mockito allows us to create and configure mock objects. Using Mockito simplifies the development of tests for classes with external dependencies significantly. We can create the mock objects manually or can use the mocking framewors like Mockito, EasyMock. jMock etc. Mock frameworks allow us to create mock objects at runtime and define their behavior. The classical example for a mock object is a data provider. In production a real database is used, but for testing a mock object simulates the database and ensures that the test conditions are always the same.
2. Creating a project
Below are the steps we need to take to create the project.
- Open Eclipse. Go to File=>New=>Java Project. In the ‘Project name’ enter ‘MockitoJUnitExample’.
- Eclipse will create a ‘src’ folder. Right click on the ‘src’ folder and choose New=>Package. In the ‘Name’ text-box enter ‘com.javacodegeeks’. Click ‘Finish’.
- Right click on the package and choose New=>Class. Give the class name as JUnitMockitoExample. Click ‘Finish’. Eclipse will create a default class with the given name.
2.1 Dependencies
For this example we need the junit and mockito jars. These jars can be downloaded from Maven repository. We are using ‘junit-4.12.jar’ and ‘mockito-all-1.10.19.jar’. There are the latests (non-beta) versions available as per now. To add these jars in the classpath right click on the project and choose Build Path=>Configure Build Path. The click on the ‘Add External JARs’ button on the right hand side. Then go to the location where you have downloaded these jars. Then click ok.
3. Verify interactions
In this section we will see how we can verify the mock object interactions. We will make use of the java.util.Set
interface for this. First we will create the mock Set
by calling the org.mockito.Mockito.mock()
method and passing the Set
class to it as a parameter.
Set mockSet = mock(Set.class);
The mock()
method creates mock object of given class or interface.
Now we will call two methods (addAll() and clear()
) of the Set
class on this mock object as shown below:
mockSet.addAll(toAdd); mockSet.clear();
Now we will verify that these methods have been called
verify(mockSet).addAll(toAdd); verify(mockSet).clear();
This verifies certain behavior happened once. Argument passed are compared using equals()
method. Below is the snippet of the full method:
@Test public void verifyInteractions() { Set mockSet = mock(Set.class); Set<String> toAdd = new HashSet<String>(); mockSet.addAll(toAdd); mockSet.clear(); verify(mockSet).addAll(toAdd); verify(mockSet).clear(); }
4. Stub method calls
In this section we will see how to stub method calls. We will again make use of the Set
class for to demonstrate this. First we will create a mock of the Set
class by calling the mock()
method:
Set mockSet = mock(Set.class);
Now we will use the when()
and thenReturn()
method to define the behavior of size()
method as below:
when(mockSet.size()).thenReturn(10);
To check that the stubbing is done correctly we will call the size()
method to see what it returns.
Assert.assertEquals(10, mockSet.size());
Below is the snippet of the whole test method:
@Test public void stubMethodCalls() { Set mockSet = mock(Set.class); when(mockSet.size()).thenReturn(10); Assert.assertEquals(10, mockSet.size()); }
5. Spy
Spy is used for partial mocking. It creates a spy of the real object. The spy calls real methods unless they are stubbed. Real spies should be used carefully and occasionally, for example when dealing with legacy code. Sometimes it’s impossible or impractical to use when(Object) for stubbing spies. Therefore for spies it is recommended to always use doReturn|Answer|Throw()|CallRealMethod family of methods for stubbing.
@Test public void testSpy() { List list = new LinkedList(); List spy = spy(list); try { when(spy.get(0)).thenReturn("foo"); } catch(IndexOutOfBoundsException e) { // Expected } doReturn("foo").when(spy).get(0); }
Mockito does not delegate calls to the passed real instance, instead it actually creates a copy of it. So if you keep the real instance and interact with it, don’t expect the spied to be aware of those interaction and their effect on real instance state. The corollary is that when an *unstubbed* method is called *on the spy* but *not on the real instance*, you won’t see any effects on the real instance. Note that the spy won’t have any annotations of the spied type, because CGLIB won’t rewrite them. It may troublesome for code that rely on the spy to have these annotations.
6. InjectMocks
@InjectMock
allows shorthand mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won’t report failure; i.e. you will have to provide dependencies yourself.
Constructor injection: the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. If the object is successfully created with the constructor, then Mockito won’t try the other strategies. Mockito has decided to no corrupt an object if it has a parametered constructor. If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won’t happen. In these cases, you will have to satisfy dependencies yourself.
Property setter injection: mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there is several property of the same type, by the match of the property name and the mock name. If you have properties with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Field injection: mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there is several property of the same type, by the match of the field name and the mock name. If you have fields with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Now we will see an example of this.
First we will create a domain class. This class represents the Report entity.
ReportEntity.java
package com.javacodegeeks.initmocks; import java.util.Date; /** * Report entity. * @author Meraj */ public class ReportEntity { private Long reportId; private Date startDate; private Date endDate; private byte[] content; public Long getReportId() { return reportId; } public void setReportId(Long reportId) { this.reportId = reportId; } public Date getStartDate() { return startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; } }
Now we will create create an interface which will refer to the above defined entity class.
IReportGenerator.java
package com.javacodegeeks.initmocks; /** * Interface for generating reports. * @author Meraj */ public interface IReportGenerator { /** * Generate report. * @param report Report entity. */ void generateReport(ReportEntity report); }
Now we will define a service which will have reference to this interface.
ReportGeneratorService.java
package com.javacodegeeks.initmocks; import java.util.Date; /** * Service class for generating report. * @author Meraj */ public class ReportGeneratorService { private IReportGenerator reportGenerator; /** * Generate report. * @param startDate start date * @param endDate end date * @param content report content */ public void generateReport(Date startDate, Date endDate, byte[] content) { ReportEntity report = new ReportEntity(); report.setContent(content); report.setStartDate(startDate); report.setEndDate(endDate); reportGenerator.generateReport(report); } }
Now we will define out test class. In the test class we will will annotate the ReportGeneratorService
class with @InjectMocks
.
@InjectMocks private ReportGeneratorService reportGeneratorService;
The IReportGenerator
class will be annotated with the @Mock
annotation.
@Mock private IReportGenerator reportGenerator;
In the setup method we will initialize the mocks.
@Before public void setUp() { MockitoAnnotations.initMocks(this); }
7. Argument Matchers
Mockito verifies argument values in natural java style: by using an equals()
method. Sometimes, when extra flexibility is required then you might use argument matchers. Argument matchers allow flexible verification or stubbing. If you are using argument matchers, all arguments have to be provided by matchers. Matcher methods like anyObject(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null). This implementation is due to static type safety imposed by the java compiler. The consequence is that you cannot use anyObject(), eq() methods outside of verified/stubbed method.
ArgumentCaptor is a special implementation of an argument matcher that captures argument values for further assertions:
ArgumentCaptor<Report> argument = ArgumentCaptor.forClass(Report.class); verify(mock).doSomething(argument.capture()); assertEquals(ReportType.PAYMENT_REPORT, argument.getValue().getType());
8. Download the source file
In this example we saw how we can use Mockito to write JUnit tests.
You can download the full source code of this example here: Mockito JUnit Example
i need test cases for get,put,delete and add method