JUnit Mockito Interview Questions

JUnit Mockito Interview Question and Answer for fresher and experienced | Also see:- Unit Testing in Java, JUnit Annotations with Examples, JUnit Assert Methods Example, Mockito With Examples, Spring Boot Rest API Unit Testing (JUnit with Mockito)

1. What is Mockito in JUnit?

Mockito is a Java-based mocking framework used for unit testing of Java applications. It is used in conjunction with other testing frameworks such as JUnit and TestNG. It internally uses Java Reflection API in order to create mock objects for a given interface. Mock objects are nothing but proxies for actual implementations.

We can use the following dependency:-

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.12.0</version>
    <scope>test</scope>
</dependency>

In the Spring environment, the spring-boot-starter-test dependency includes junit-jupiter, vintage, and mockito dependencies.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
</dependency>

To mock the object we use the:-

@SpringBootTest
public class EmployeeServiceImplTest {

    @InjectMocks
    EmployeeServiceImpl employeeServiceImpl;

    @Mock
    EmployeeCrudRepo repo;

    @Test
    public void getEmpByIdTest() {
        when(repo.findById(1L)).thenReturn(Optional.of(createEmployeeStub()));
        Employee testedEmp = employeeServiceImpl.getEmpById(1L);
        assertEquals(testedEmp.getName(), "ABC");
    }

    private Employee createEmployeeStub() {
        Employee employee = new Employee();
        employee.setName("ABC");
        return employee;
    }
}

Here’s a brief explanation of the annotations:

  • @InjectMocks: Automatically injects mocked dependencies into the tested object.
  • @Mock: Creates a mock instance of a class.
  • @Test: Marks a method as a test case.

2. What is Mocking?

  • Mocking is a process of developing the objects that act as the mock or clone of the real objects. In other words, mocking is a testing technique where mock objects are used instead of real objects for testing purposes. Mock objects provide a specific (dummy) output for a particular (dummy) input passed to it.
  • Mocking for unit testing is when you create an object that implements the behavior of a real subsystem in controlled ways. In short, mocks are used as a replacement for a dependency.
  • To mock objects, you need to understand these key concepts of mocking, i.e., stub, fake, spy, dummy, and mock. Some of the unit tests involve only stubs, whereas some involve fake, and mocks.
  • A method invoked using mocked reference does not execute the actual method body defined in the class file, rather the method behavior is configured using when(…).thenReturn(…) methods.

3. What are @Mock and @InjectMocks?

  • In mockito-based JUnit tests, @Mock annotation creates mocks and @InjectMocks creates actual objects and injects mocked dependencies into it.
  • We must define the when(…).thenReturn(…) methods for mock objects whose class methods will be invoked during actual test execution.
  • So In a JUnit test, we create objects (@InjectMocks) for the class that needs to be tested and its methods to be invoked using inject mock.
  • We create mocks (@Mock) for the dependencies that will not be present in the test environment and objects are dependent on it to complete the method call.

4. Benefits of Mocking?

  • No Hardcoding – No need to write mock objects on your own.
  • Refactoring Safe – Renaming interface method names or reordering parameters will not break the test code as Mocks are created at runtime using java reflection API.
  • Return value support – Supports return values. when(repo.findById(1L)).thenReturn(Optional.of(createEmployeeStub()));
  • Exception support – Supports exceptions.
@Test
public void getEmpByIdThrowsExceptionTest() {
    when(repo.findById(2L)).thenThrow(new RuntimeException("Employee Not Found"));

    assertThrows(RuntimeException.class, () -> {
        employeeServiceImpl.getEmpById(2L);
    });
}
  • Order check support – Supports check on the order of method calls.
  • Annotation support – Supports creating mocks using annotation.

5. Disadvantages of Mocking?

  • Mockito can’t mock everything out of the box.
  • In case we want to mock final or static methods, equals(), or the construction of an object, we need PowerMock.

6. Why do you need Mocking in the first place?

Common targets for mocking are:

  • Database connections – Sometimes the database queries can take 10, 20, or more seconds to execute.
  • Classes that are slow.
  • Classes with side effects like who sends email to clients.
  • If we want to test a component that depends on the other component, but it is under development. Without mocking, we need to wait for the completion of the required elements for testing.
  • Web services / External resources. Connecting to an external resource can take too much time and can be down which impacts our testing. Our CI/CD pipeline may break because of another web service.

7. Junit Coverage?

For each Java project, a minimum of 80% code coverage is required, we have many tools out there for coverage check. For example:- EclEmma Java Code Coverage tool in Eclipse/STS marketplace. These tools can tell how much code has been covered through test cases. Select project > Right click > Coverage As > JUnit Test.

8. Difference between doReturn and thenReturn?
Mockito provides two different syntaxes for creating stubs like:-

  • doReturn and thenReturn
  • doNothing (no thenNothing)
  • doThrow and thenThrow

The thenReturn ways of stubbing is a type-sage way of setting up stubs. What this essentially means is that it does a compile-time check against the return types that you want to stub too.

9. What’s the need to verify that the mock was called?

  • Setting up a stub on a mocked object (or a spied instance) does not guarantee whether the stubbed setup was even invoked.
  • “verification” matchers, give a facility to validate whether the stub that was set up was actually invoked or not, how many times was the call made, what arguments were the stubbed method called with, etc.
  • In essence, it allows us to verify the test setup and expected outcome in a more robust manner.

10. When and why should a spy be used?
Spy is a type of partial mock supported by Mockito. This essentially means is a type of instance where:-

  • When no mock is set up, any interaction on spy results in calling the real methods. But it still allows you to verify the interactions with the spied object like – was a method actually called, how many times the method was called, what were the arguments using which the method was called, etc.
  • It gives you the flexibility to set up partial mocks.

11. Example

Create a Spring starter project with the following dependencies:- Spring Web, Spring Data JPA, MySQL Driver, and Lombok.

In application.properties:-

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update

Entity Class:-

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
}

Repository Interface:-

public interface EmployeeRepo extends JpaRepository<Employee, Integer> { }

Service Class:-

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepo repo;

    public Employee getEmpById(Integer id) {
        try {
            Employee e = repo.findById(id).get();
            if (e.getName().equalsIgnoreCase("jerry")) {
                throw new IllegalArgumentException("Not allowed to access this employee");
            }
            return e;
        } catch (NoSuchElementException e) {
            throw e;
        }
    }
}

Test Class:-

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;

import java.util.NoSuchElementException;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class EmployeeServiceTest {
    @InjectMocks
    EmployeeService employeeService;

    @Mock
    EmployeeRepo repo;

    @Test
    public void getEmpByIdTest() {
        when(repo.findById(1)).thenReturn(createEmployeeStub());
        Employee testedEmployee = employeeService.getEmpById(1);
        assertEquals(testedEmployee.getName(), "ABC");
    }

    @Test
    public void getEmpByIdTestWithException1() {
        when(repo.findById(1)).thenReturn(createEmployeeStubWithException());
        assertThrows(IllegalArgumentException.class, () -> {
            employeeService.getEmpById(1);
        });
    }

    @Test
    public void getEmpByIdTestWithException2() {
        when(repo.findById(1)).thenReturn(Optional.empty());
        assertThrows(NoSuchElementException.class, () -> {
            employeeService.getEmpById(1);
        });
    }

    private Optional<Employee> createEmployeeStub() {
        Employee stubEmp = new Employee();
        stubEmp.setName("ABC");
        return Optional.of(stubEmp);
    }

    private Optional<Employee> createEmployeeStubWithException() {
        Employee stubEmp = new Employee();
        stubEmp.setName("Jerry");
        return Optional.of(stubEmp);
    }
}

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

Your email address will not be published. Required fields are marked *