Spring Boot + PowerMock + JUnit 5 Tutorial

Introduction

PowerMock is a Java framework that allows you to mock static methods, constructors, final classes, and more. This makes it a powerful tool for unit testing. Integrating PowerMock with JUnit 5 requires some additional configuration. In this tutorial, we will cover how to set up a Spring Boot 3 application and use PowerMock with JUnit 5 for testing.

Prerequisites

  1. Java Development Kit (JDK) 17 or later
  2. Apache Maven installed
  3. An IDE like IntelliJ IDEA or Eclipse

Step 1: Create a Spring Boot Project

You can create a Spring Boot project using Spring Initializr or your IDE.

Using Spring Initializr

  1. Go to Spring Initializr.
  2. Select the following options:
    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.0.0 or later
    • Group: com.example
    • Artifact: powermock-demo
    • Name: powermock-demo
    • Package name: com.example.powermockdemo
    • Packaging: Jar
    • Java: 17 or later
  3. Add the following dependencies:
    • Spring Web
    • Spring Boot Starter Test
  4. Click "Generate" to download the project zip file.
  5. Extract the zip file and open the project in your IDE.

Step 2: Add PowerMock Dependencies

Add the following dependencies to your pom.xml file:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- PowerMock Dependencies -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>2.0.9</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>2.0.9</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit5</artifactId>
        <version>2.0.9</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Step 3: Create a Simple Service

Create a new Java class named UtilityService in the com.example.powermockdemo package:

package com.example.powermockdemo;

public class UtilityService {

    public static String getStaticMessage() {
        return "Hello from static method!";
    }

    public String getMessage() {
        return "Hello from instance method!";
    }
}

Explanation: The UtilityService class contains both a static method getStaticMessage and an instance method getMessage that we will mock in our tests.

Step 4: Create a Controller

Create a new Java class named UtilityController in the com.example.powermockdemo package:

package com.example.powermockdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UtilityController {

    @Autowired
    private UtilityService utilityService;

    @GetMapping("/message")
    public String getMessage() {
        return utilityService.getMessage();
    }

    @GetMapping("/static-message")
    public String getStaticMessage() {
        return UtilityService.getStaticMessage();
    }
}

Explanation: The UtilityController class has two endpoints: one for the instance method and one for the static method in UtilityService.

Step 5: Create a PowerMock Test Class

Create a new test class named UtilityControllerTest in the src/test/java/com/example/powermockdemo package:

package com.example.powermockdemo;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit5.PowerMockExtension;

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

@ExtendWith(PowerMockExtension.class)
@PrepareForTest(UtilityService.class)
public class UtilityControllerTest {

    @Mock
    private UtilityService utilityService;

    @InjectMocks
    private UtilityController utilityController;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testGetMessage() {
        // Mocking the instance method
        when(utilityService.getMessage()).thenReturn("Mocked instance message");

        // Calling the controller method
        String message = utilityController.getMessage();

        // Asserting the result
        assertEquals("Mocked instance message", message);
    }

    @Test
    public void testGetStaticMessage() {
        // Mocking the static method
        PowerMockito.mockStatic(UtilityService.class);
        PowerMockito.when(UtilityService.getStaticMessage()).thenReturn("Mocked static message");

        // Calling the controller method
        String message = utilityController.getStaticMessage();

        // Asserting the result
        assertEquals("Mocked static message", message);
    }
}

Explanation:

  • @ExtendWith(PowerMockExtension.class): Integrates PowerMock with JUnit 5.
  • @PrepareForTest(UtilityService.class): Prepares UtilityService for testing with PowerMock.
  • In testGetMessage, we mock the instance method getMessage using Mockito.
  • In testGetStaticMessage, we mock the static method getStaticMessage using PowerMock.

Step 6: Run the Tests

Run the tests using your IDE or by executing the following command in the terminal:

mvn test

You should see an output indicating that all tests have passed successfully.

Conclusion

In this tutorial, we demonstrated how to use PowerMock with JUnit 5 in a Spring Boot 3 application. We created a simple Spring Boot application, added PowerMock dependencies, and wrote tests to mock both instance and static methods. 

By following these steps, you can efficiently test your Spring Boot applications and ensure that even the most complex scenarios are properly tested. This approach allows you to mock static methods, constructors, and more, making your tests more robust and reliable.

Comments