In this post, We will learn about @Mock and @Spy Mockito Annotations With Example?
@ Mock Annotation
- The most Frequently used annotation in Mockito is @Mock
- Use @Mock annotation to create and inject mocked instances without having to call Mockito.mock(abc.class) manually.
- We may use org.mockito.Mockito class mock() method to create a mock object of a given class or interface.
@Spy Annotation
- Use @Spyannotation to spy on an existing instance
- We usually use Mockito Spy to partial mock an object. When we spy on an object then the real methods are being called unless it’s stubbed.
Let’s try to understand the above concept using a demo project
pom.xml
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 |
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.intotech</groupId> <artifactId>MockAndSpyInMockitoExample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.target>8</maven.compiler.target> <maven.compiler.source>8</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>3.5.7</version> <scope>test</scope> </dependency> </dependencies> </project> |
EmployeeDAO.java
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.infotech.dao; import java.util.List; import com.infotech.model.Employee; public interface EmployeeDAO { public abstract void createEmployee(Employee employee); public abstract Employee getEmployeeById(Integer employeeId); public abstract void updateEmployeeEmailById(String newEmail,Integer employeeId); public abstract void deleteEmployeeById(Integer employeeId); public abstract List<Employee> getAllEmployeesInfo(); } |
EmployeeDAOImpl.java
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
package com.infotech.dao.impl; import java.math.BigDecimal; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import com.infotech.dao.EmployeeDAO; import com.infotech.model.Employee; import com.infotech.util.DBUtil; public class EmployeeDAOImpl implements EmployeeDAO { @Override public void createEmployee(Employee employee) { String SQL = "INSERT INTO employee_table(employee_name,email,salary,date_of_joining,bonus)VALUES(?,?,?,?,?)"; try(Connection connection = DBUtil.getConnection();PreparedStatement ps = connection.prepareStatement(SQL)) { ps.setString(1, employee.getEmployeeName()); ps.setString(2, employee.getEmail()); ps.setDouble(3, employee.getSalary()); ps.setDate(4, new Date(employee.getDoj().getTime())); ps.setBigDecimal(5, employee.getBonus()); int executeUpdate = ps.executeUpdate(); if(executeUpdate ==1){ System.out.println("Employee is crated.."); } } catch (Exception e) { e.printStackTrace(); } } @Override public Employee getEmployeeById(Integer employeeId) { Employee employee = null; String SQL = "SELECT *FROM employee_table WHERE employee_id=?"; try(Connection connection = DBUtil.getConnection();PreparedStatement ps = connection.prepareStatement(SQL)) { ps.setInt(1, employeeId); ResultSet rs = ps.executeQuery(); if (rs.next()) { int empId = rs.getInt("employee_id"); String eName = rs.getString("employee_name"); String email = rs.getString("email"); Double salary = rs.getDouble("salary"); BigDecimal bonus = rs.getBigDecimal("bonus"); Date date = rs.getDate("date_of_joining"); employee = new Employee(); employee.setEmployeeName(eName); employee.setBonus(bonus); employee.setDoj(date); employee.setEmail(email); employee.setEmployee_id(empId); employee.setSalary(salary); } } catch (Exception e) { e.printStackTrace(); } return employee; } @Override public void updateEmployeeEmailById(String newEmail, Integer employeeId) { String SQL = "UPDATE employee_table set email=? WHERE employee_id=?;"; try(Connection connection = DBUtil.getConnection();PreparedStatement ps = connection.prepareStatement(SQL)) { ps.setString(1, newEmail); ps.setInt(2,employeeId); int executeUpdate = ps.executeUpdate(); if(executeUpdate ==1){ System.out.println("Employee email is updated.."); } } catch (Exception e) { e.printStackTrace(); } } @Override public void deleteEmployeeById(Integer employeeId) { String SQL = "DELETE FROM employee_table WHERE employee_id=?;"; try(Connection connection = DBUtil.getConnection();PreparedStatement ps = connection.prepareStatement(SQL)) { ps.setInt(1,employeeId); int executeUpdate = ps.executeUpdate(); if(executeUpdate ==1){ System.out.println("Employee is deleted with ID::"+employeeId); } } catch (Exception e) { e.printStackTrace(); } } @Override public List<Employee> getAllEmployeesInfo() { List<Employee> empList = new ArrayList<>(); String SQL = "SELECT *FROM employee_table"; try(Connection connection = DBUtil.getConnection();PreparedStatement ps = connection.prepareStatement(SQL)) { ResultSet rs = ps.executeQuery(); while (rs.next()) { int empId = rs.getInt("employee_id"); String eName = rs.getString("employee_name"); String email = rs.getString("email"); Double salary = rs.getDouble("salary"); BigDecimal bonus = rs.getBigDecimal("bonus"); Date date = rs.getDate("date_of_joining"); Employee employee = new Employee(); employee.setEmployeeName(eName); employee.setBonus(bonus); employee.setDoj(date); employee.setEmail(email); employee.setEmployee_id(empId); employee.setSalary(salary); empList.add(employee); } } catch (Exception e) { e.printStackTrace(); } return empList; } } |
EmpoyeeService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.infotech.service; import java.util.List; import com.infotech.model.Employee; public interface EmpoyeeService { public abstract void createEmployee(Employee employee); public abstract Employee fetchEmployeeById(Integer employeeId); public abstract void updateEmployeeEmailById(String newEmail,Integer employeeId); public abstract void deleteEmployeeById(Integer employeeId); public abstract List<Employee> fetchAllEmployeesInfo(); } |
EmployeeServiceImpl.java
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 |
package com.infotech.service; import java.util.List; import com.infotech.dao.EmployeeDAO; import com.infotech.dao.impl.EmployeeDAOImpl; import com.infotech.model.Employee; public class EmployeeServiceImpl implements EmpoyeeService { private EmployeeDAO employeeDAO = new EmployeeDAOImpl(); @Override public void createEmployee(Employee employee) { employeeDAO.createEmployee(employee); } @Override public Employee fetchEmployeeById(Integer employeeId) { return employeeDAO.getEmployeeById(employeeId); } @Override public void updateEmployeeEmailById(String newEmail, Integer employeeId) { employeeDAO.updateEmployeeEmailById(newEmail, employeeId); } @Override public void deleteEmployeeById(Integer employeeId) { employeeDAO.deleteEmployeeById(employeeId); } @Override public List<Employee> fetchAllEmployeesInfo() { return employeeDAO.getAllEmployeesInfo(); } } |
DBUtil.java
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 |
package com.infotech.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String DB_DRIVER_CLASS = "com.mysql.cj.jdbc.Driver"; private static final String DB_USERNAME = "root"; private static final String DB_PASSWORD = "root"; private static final String DB_URL = "jdbc:mysql://localhost:3306/test"; private static Connection connection = null; static{ try { Class.forName(DB_DRIVER_CLASS); connection = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } } public static Connection getConnection(){ return connection; } } |
Employee.java
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 52 53 54 55 56 |
package com.infotech.model; import java.math.BigDecimal; import java.util.Date; public class Employee { private int employee_id; private String employeeName; private String email; private Double salary; private Date doj; private BigDecimal bonus; public int getEmployee_id() { return employee_id; } public void setEmployee_id(int employee_id) { this.employee_id = employee_id; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public Date getDoj() { return doj; } public void setDoj(Date doj) { this.doj = doj; } public BigDecimal getBonus() { return bonus; } public void setBonus(BigDecimal bonus) { this.bonus = bonus; } @Override public String toString() { return "Employee [employee_id=" + employee_id + ", employeeName=" + employeeName + ", email=" + email + ", salary=" + salary + ", doj=" + doj + ", bonus=" + bonus + "]"; } } |
ClientTest.java
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 |
package com.infotech.client; import java.math.BigDecimal; import java.util.Date; import java.util.List; import com.infotech.model.Employee; import com.infotech.service.EmployeeServiceImpl; import com.infotech.service.EmpoyeeService; public class ClientTest { public static void main(String[] args) { EmpoyeeService empoyeeService = new EmployeeServiceImpl(); Employee employee = getEmployee(); empoyeeService.createEmployee(employee); //getEmployeeById(empoyeeService); //empoyeeService.updateEmployeeEmailById("[email protected]", 3); //empoyeeService.deleteEmployeeById(4); //getAllEmployeesInfo(empoyeeService); } private static void getAllEmployeesInfo(EmpoyeeService empoyeeService) { List<Employee> empList = empoyeeService.fetchAllEmployeesInfo(); for (Employee employee : empList) { System.out.println(employee); } } private static void getEmployeeById(EmpoyeeService empoyeeService) { Employee employee2 = empoyeeService.fetchEmployeeById(1); if(employee2 != null){ System.out.println(employee2); }else{ System.out.println("Employee does not exist.."); } } private static Employee getEmployee() { Employee employee = new Employee(); employee.setBonus(new BigDecimal(600)); employee.setDoj(new Date()); employee.setEmployeeName("KK"); employee.setSalary(50000.00); return employee; } } |
DbScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
CREATE TABLE `employee_table` ( `employee_id` int(11) NOT NULL auto_increment, `employee_name` varchar(60) NOT NULL, `email` varchar(45) NOT NULL, `salary` double default NULL, `date_of_joining` datetime default NULL, `bonus` decimal(10,0) default NULL, PRIMARY KEY (`employee_id`) ) ; INSERT INTO employee_table(employee_name,email,salary,date_of_joining,bonus) INSERT INTO employee_table(employee_name,email,salary,date_of_joining,bonus) |
Database Screen Shot
Building the Test Class using Junit 5 and Mockito 3
Let’s build our test classes and use the Mockito extension for it.
Use of @Mock Annotation
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 |
package com.infotech.service; import static org.mockito.Mockito.when; import java.math.BigDecimal; import java.util.Date; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import com.infotech.model.Employee; /** * @author KK JavaTutorials * Use of @Mock Annotation * */ @ExtendWith(value = { MockitoExtension.class }) public class MockEmpoyeeServiceTest_1 { @Mock private EmployeeServiceImpl employeeService; @Test public void testFetchEmployeeById() { when(employeeService.fetchEmployeeById(2)).thenReturn(getEmployee()); Employee employee = employeeService.fetchEmployeeById(2); System.out.println(employee); } private static Employee getEmployee() { Employee employee = new Employee(); employee.setEmployee_id(2); employee.setBonus(new BigDecimal(600)); employee.setDoj(new Date()); employee.setEmployeeName("KK"); employee.setSalary(50000.00); return employee; } } |
Console Output of Above Test class when you run as JUnit Test:
Employee [employee_id=2, employeeName=KK, [email protected], salary=50000.0, doj=Thu Oct 08 09:32:54 IST 2020, bonus=600]
Use of mock 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 |
package com.infotech.service; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.math.BigDecimal; import java.util.Date; import org.junit.jupiter.api.Test; import com.infotech.model.Employee; /** * @author KK JavaTutorials * Use of mock method */ public class MockEmpoyeeServiceTest_2 { @Test public void testFetchEmployeeById() { EmployeeServiceImpl employeeService = mock(EmployeeServiceImpl.class); when(employeeService.fetchEmployeeById(2)).thenReturn(getEmployee()); Employee employee = employeeService.fetchEmployeeById(2); System.out.println(employee); } private static Employee getEmployee() { Employee employee = new Employee(); employee.setEmployee_id(2); employee.setBonus(new BigDecimal(600)); employee.setDoj(new Date()); employee.setEmployeeName("KK"); employee.setSalary(50000.00); return employee; } } |
Console Output of Above Test class when you run as JUnit Test:
Employee [employee_id=2, employeeName=KK, [email protected], salary=50000.0, doj=Thu Oct 08 09:34:01 IST 2020, bonus=600]
Use of @Spy Annotation
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 |
package com.infotech.service; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import com.infotech.model.Employee; /** * @author KK JavaTutorials * Use of @Spy Annotation */ @ExtendWith(value = { MockitoExtension.class }) public class SpyEmpoyeeServiceTest_1 { @Spy private EmployeeServiceImpl employeeService; @Test public void testFetchEmployeeById() { System.out.println(employeeService.hashCode()); Employee employee = employeeService.fetchEmployeeById(2); System.out.println(employee); } } |
Console Output of Above Test class when you run as JUnit Test:
Employee [employee_id=2, employeeName=John, email=j[email protected], salary=90000.0, doj=2020-08-28, bonus=290]
Use of spy method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.infotech.service; import static org.mockito.Mockito.spy; import org.junit.jupiter.api.Test; import com.infotech.model.Employee; /** * @author KK JavaTutorials * Use of spy method */ public class SpyEmpoyeeServiceTest_2 { @Test public void testFetchEmployeeById() { EmployeeServiceImpl employeeService = spy(EmployeeServiceImpl.class); Employee employee = employeeService.fetchEmployeeById(2); System.out.println(employee); } } |
Console Output of Above Test class when you run as JUnit Test:
Employee [employee_id=2, employeeName=John, email=j[email protected], salary=90000.0, doj=2020-08-28, bonus=290]
You May Also Like:
What is Mocking?
Why Need for mocking?
What are the Benefits of Mockito?
How to mock interface using Mockito example?
Mockito and JUnit Integration Using Maven Example
@InjectMocks Annotation in Mockito with Example
Mockito – Verifying Method Calls
@Captor Annotation in Mockito with Example
Adding behavior to mocked object in Mockito
Mocking Void Methods with Mockito
Mocking Exception Throwing using Mockito
Mockito’s mock Overloaded Methods
That’s all about @Mock and @Spy Mockito Annotations With Example?
If you have any feedback or suggestion please feel free to drop in below comment box.