Open In App

How to Use @Autowired and @InjectMocks in Spring Boot Tests?

Last Updated : 23 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In Spring Boot application development, writing the unit tests is essential for the ensuring that the application behaves as the expected. Testing can be challenging, especially when dealing with dependencies and their instantiation. This is where the annotations like @Autowired and @InjectMocks come into play. They can simplify the process of injecting dependencies in the tests, making it easier to isolate components for the testing.

Prerequisites

  • Basic knowledge of the Java and Spring Boot.
  • Familiarity with testing concepts, particularly using JUnit.
  • Maven for building dependency management.
  • JDK and IntelliJ IDEA installed in your system.

Main Concept: Using @Autowired and @InjectMocks in Spring Boot Tests

What is @Autowired?

The @Autowired annotation is part of the Spring Framework. It can be used to automatically inject dependencies into Spring components. This can be particularly useful in the tests where you need to inject the mock or the real implementation of the dependency into the service or controller.

What is @InjectMocks?

The @InjectMocks annotation provided by the Mockito framework, it can be used to create the instance of the class and inject the mocks created with @Mock into it. This can be particularly useful for the unit testing service classes, where you want to isolate the class under the test by mocking its dependencies.

Comparison of @Autowired and @InjectMocks

  • @Autowired: This annotation can be used in the Spring tests to inject dependencies from the Spring application context.
  • @InjectMocks: This annotation can be used in the unit tests with Mockito to the inject mock objects into the class being tested.

Example Project: Using @Autowired and @InjectMocks in Spring Boot Tests

This example project showcasing the use of the @Autowired and @InjectMocks in the Spring Boot application. The project will implement the simple User service with corresponding repository and test classes to the demonstrate the usage of these annotations effectively.

Step 1: Create a new Spring Boot Project

Create the new Spring Boot Project using the IntelliJ IDEA. Choose the following options:

  • Name: user-management-system
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

testinject1

Step 2: Add the Dependencies

Add the following dependencies into the Spring Boot Project.

  • Spring web
  • Spring Boot DevTools
  • Lombok
  • MySQL Driver
  • Spring Data JPA

Click on the Create button.

testinject2

Project Structure

Once created the project, we will setup the file structure looks like the below image:

testinject3


Step 3: Configure Application Properties

Open the application.properties file and add the following MySQL and Hibernate configuration into the Spring Boot Project.

spring.application.name=user-management-system

# MySQL Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=mypassword

# Hibernate Configuration
spring.jpa.show-sql=true

# JPA Configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect


Step 4: Create the User Class

Java
package com.gfg.usermanagementsystem;


import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@Entity
@Table(name = "user")
public class User {
    // Getters and Setters
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    // Constructors
    public User() {}

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }

}


Step 5: Create the UserRepository Interface

Java
package com.gfg.usermanagementsystem;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}


Step 6: Create the UserService class

Java
package com.gfg.usermanagementsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findUserById(Long id) {
        Optional<User> user = userRepository.findById(id);
        return user.orElse(null);
    }

    public User saveUser(User user) {
        return userRepository.save(user);
    }
}


Step 7: Create the UserController Class

Java
package com.gfg.usermanagementsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.findUserById(id);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }
}

Step 8: Main Class

Java
package com.gfg.usermanagementsystem;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class UserManagementSystemApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserManagementSystemApplication.class, args);
    }

}


Step 9: Create the UserServiceUnitTest Class

Java
package com.gfg.usermanagementsystem;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class UserServiceUnitTest {

    @InjectMocks
    private UserService userService;

    @Mock
    private UserRepository userRepository;

    @Test
    public void testFindUserById() {
        // Arrange
        User mockUser = new User(1L, "John Doe");
        Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));

        // Act
        User user = userService.findUserById(1L);

        // Assert
        assertEquals("John Doe", user.getName());
    }
}


Step 10: Create the UserServiceIntegrationTest Class

Java
package com.gfg.usermanagementsystem;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
public class UserServiceIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private UserRepository userRepository;

    @Test
    public void testCreateUser() throws Exception {
        // Arrange
        User newUser = new User(null, "Jane Doe");

        // Act & Assert
        mockMvc.perform(post("/users")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("{\"name\":\"Jane Doe\"}"))
                .andExpect(status().isOk());

        // Verify that the user is saved in the repository
        assertEquals(1, userRepository.count());
    }
}


Step 11: MainTest Class

Java
package com.gfg.usermanagementsystem;

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

@SpringBootTest
class UserManagementSystemApplicationTests {

    @Test
    void contextLoads() {
    }

}


pom.xml

XML
<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>user-management-system</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>user-management-system</name>
    <description>user-management-system</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>


Step 12: Run the Application

Once completed the project, it will run and start at port 8080.

testinject4-compressed


Step 13: Running the Tests

We can use the following maven command to run the tests cases:

mvn test
testttt-compressed


This example project can demonstrates how to structure the Spring Boot application. It also showcases the use of the @Autowired for dependency injection in the service and controller classes and @InjectMocks for the mocking dependencies in unit tests.

Conclusion

In Conclusion, both @Autowired and @InjectMocks serve the different purposes in the Spring Boot tests. While @Autowired integrates with the Spring application context for the dependency injection, @InjectMocks can focuses on the injecting mocks into the class under test, allowing for the efficient unit testing. Understanding how to use these annotations effectively can significantly enhance the readability of the Spring Boot application.


Next Article

Similar Reads