This "Mockito tutorial: How to use Mockito for testing in spring boot" will teach you how to effectively utilize Mockito for testing within Spring Boot applications and enhance your testing practices.

What is Mockito?

Mockito, at its core, is a mocking framework tailored to Java applications. Mocking, in the context of software testing, involves creating simulated objects that mimic the behavior of real components. These mock objects enable developers to isolate specific parts of their codebase during testing, ensuring accurate validation of the code's functionality. Mockito seamlessly integrates with testing frameworks like JUnit, making it a powerful asset in a developer's toolkit.




How to use Mockito for JUnit testing?

Using Mockito for JUnit Testing: The marriage of Mockito and JUnit facilitates effective unit testing. The process can be broken down into several steps:

1.      Dependency Inclusion: Begin by adding the Mockito library to your project's build configuration, typically via your dependency management tool.

2.      Creating Mocks: Utilize Mockito to generate mock objects representing the dependencies or collaborators of your code under test.

3.      Behaviour Specification: Define the expected behaviour of these mock objects using Mockito's API. Set up method calls and return values as needed.

4.      Test Invocation: Write your test code that interacts with the code under test and its mock dependencies.

5.      Interaction Verification: After executing the test code, utilize Mockito's verification methods to ensure that the expected interactions between the code under test and its dependencies occurred.

 

Mockito in Spring Boot with example:

In Spring Boot applications, Mockito plays a crucial role in unit testing by allowing developers to isolate individual components for focused validation. It aids in separating concerns and validating the interactions between various layers of the application, such as services, repositories, and controllers, without requiring access to the actual database or external services.

Common Methods and Annotations:

1.      Mockito.mock(): Creates a mock object of a class or interface.

2.      Mockito.spy(): Creates a spy object (partial mock) of a real object.

3.      Mockito.when(): Defines the behavior of methods on mock objects.

4.      Mockito.doReturn(): Alternative to when() for specifying method behavior.

5.      Mockito.doThrow(): Specifies that a method on a mock object should throw an exception.

6.      Mockito.doNothing(): Specifies that a void method on a mock object should do nothing.

7.      Mockito.verify(): Verifies that methods were called on mock objects.

8.      MockitoAnnotations.initMocks(): Initializes objects annotated with @Mock, @Spy, and @InjectMocks.

9.      @Mock Annotation: Creates a mock object.

10.   @Spy Annotation: Creates a spy object (partial mock).

11.   @InjectMocks Annotation: Injects mocked dependencies into the class under test.

12.   @Captor Annotation: Captures method arguments for verification.

 

Comprehensive Example:

In this example, we'll consider a Spring Boot application that manages orders and products. We'll use Mockito to test the interactions between the OrderService and the ProductService while demonstrating various Mockito methods and annotations.

Assuming you have the following service classes:

@Service

public class OrderService {

 

    @Autowired

    private ProductService productService;

 

    public double calculateOrderTotal(String... items) {

        double total = 0.0;

        for (String item : items) {

            total += productService.getPrice(item);

        }

        return total;

    }

}

 

@Service

public class ProductService {

 

    public double getPrice(String item) {

        // Fetch price from external source

        return /* ... */;

    }

}


Here's a comprehensive example showcasing the usage of the methods and annotations listed above:

@RunWith(MockitoJUnitRunner.class)

public class OrderServiceTest {

 

    @InjectMocks

    private OrderService orderService;

 

    @Spy

    private ProductService productService;

 

    @Captor

    private ArgumentCaptor<String> itemCaptor;

 

    @Test

    public void testCalculateOrderTotal() {

        // Mocking the behavior of ProductService

        Mockito.doReturn(10.0).when(productService).getPrice("item1");

        Mockito.doReturn(20.0).when(productService).getPrice("item2");

 

        // Testing the OrderService

        double total = orderService.calculateOrderTotal("item1", "item2");

 

        Assert.assertEquals(30.0, total, 0.01);

        Mockito.verify(productService).getPrice("item1");

        Mockito.verify(productService).getPrice("item2");

    }

 

    @Test(expected = IllegalArgumentException.class)

    public void testProcessOrderWithInvalidItem() {

        // Mocking an exception throw

        Mockito.doThrow(IllegalArgumentException.class)
                      .when(productService)
                      .getPrice("invalidItem");

 

        // Testing exception handling in OrderService

        orderService.calculateOrderTotal("invalidItem");

    }

 

    @Test

    public void testSaveOrderWithoutExceptions() {

        // Mocking ProductService behavior and OrderRepository save method

        Mockito.doReturn(5.0).when(productService).getPrice("item3");

        Mockito.doNothing().when(orderRepository).save(Mockito
                                           .any(Order.class));

 

        Order order = new Order(/* ... */);

 

        // Testing OrderService

        orderService.saveOrder(order);

 

        Mockito.verify(productService).getPrice(itemCaptor.capture());

        Assert.assertEquals("item3", itemCaptor.getValue());

    }

}

 

In this example, we've demonstrated the usage of various Mockito methods and annotations, such as doReturn(), doThrow(), doNothing(), verify(), @Spy, @Captor, and more. This comprehensive test suite ensures that the interactions between the OrderService and the ProductService are correctly validated, while handling different scenarios and exceptions gracefully.

What is Mockito vs JUnit?

here's a comparison between Mockito and JUnit in a table format:

Aspect

Mockito

JUnit

Purpose

Mocking framework for creating mock objects and verifying interactions.

Testing framework for writing and executing unit tests.

Main Usage

Creating and managing mock objects to isolate code under test.

Writing and running test cases to verify code functionality.

Focus

Interaction testing: verifying interactions between objects.

Behavior testing: verifying expected outcomes of methods.

Integration

Often used alongside testing frameworks like JUnit.

Standalone framework for writing unit tests.

Annotations

Provides annotations like @Mock, @Spy, @InjectMocks, @Captor.

Provides annotations like @Test, @Before, @After, etc.

Method Usage

Defines mock behaviors with methods like when(), doReturn(), etc.

Executes tests with methods like assertEquals(), assertTrue(), etc.

Test Isolation

Primarily focused on isolating code by mocking dependencies.

Isolates code for testing, but does not involve mocking.

Verification

Ensures interactions between objects occurred as expected.

Ensures expected outcomes of methods are met.

Examples

Verifying that methods were called, checking arguments, etc.

Checking expected return values, asserting conditions, etc.

Purpose Example

Verifying that a service method interacts with its dependencies.

Testing that a method returns the correct result or behaves as expected.

Mocking

Creates mock objects to replace real objects or dependencies.

Does not involve mocking; tests use actual objects.

Compatibility

Integrates well with JUnit and other testing frameworks.

A standalone testing framework commonly used with other tools.

Flexibility

Allows specifying behavior and interactions of mock objects.

Provides various assertion methods to verify outcomes.

Common Libraries

Mockito, PowerMock (for static methods, private methods, etc.).

JUnit, JUnit Jupiter (newer version), JUnit Vintage (for JUnit 4 compatibility).

 

Both Mockito and JUnit serve different purposes in the testing ecosystem. Mockito focuses on creating mock objects to isolate and verify interactions between components, while JUnit focuses on writing and executing test cases to verify the expected behavior of methods and functions. They often complement each other, with Mockito used to handle dependencies and interactions in JUnit test cases.

Is Mockito a mock?

No, Mockito itself is not a mock. Mockito is a mocking framework that allows you to create mock objects. A mock object is a simulated or fake version of a real object or component. Mockito provides the tools and methods to create and interact with these mock objects during unit testing. It helps you isolate the behavior of the code you're testing by simulating the behavior of its dependencies.

Is Mockito only for Java?

Yes, Mockito is primarily designed for Java applications. It provides a powerful and convenient way to create mock objects and manage their behaviors in Java unit tests. However, similar mocking frameworks and libraries exist for other programming languages as well. For example, in Python, you have libraries like unittest.mock (part of the standard library) and pytest-mock that serve similar purposes. While the concepts and goals are similar, each library is tailored to the specific programming language's syntax and features.

Conclusion:

Mockito provides a plethora of methods and annotations to facilitate comprehensive testing within a Spring Boot application. The example above demonstrates various Mockito techniques, such as spying, defining behavior, throwing exceptions, and initializing mocks. By skillfully utilizing these tools, developers can ensure the reliability and correctness of their Spring Boot services through effective unit testing.