0
0
JunitHow-ToBeginner ยท 4 min read

How to Use @InjectMocks Annotation in JUnit Tests

Use the @InjectMocks annotation in JUnit with Mockito to create an instance of the class under test and automatically inject its @Mock dependencies. This simplifies setup by letting Mockito handle dependency injection for your test objects.
๐Ÿ“

Syntax

The @InjectMocks annotation is placed on the class instance you want to test. Mockito will create this instance and inject all fields annotated with @Mock or @Spy into it.

Typical usage:

  • @Mock: Creates mock objects for dependencies.
  • @InjectMocks: Creates the class under test and injects mocks into it.
java
public class MyServiceTest {

    @Mock
    private Dependency dependency;

    @InjectMocks
    private MyService myService;

    // tests here
}
๐Ÿ’ป

Example

This example shows how @InjectMocks automatically injects a mocked dependency into the service class for testing.

java
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

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

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void testGetUserName() {
        when(userRepository.findNameById(1)).thenReturn("Alice");

        String name = userService.getUserName(1);

        assertEquals("Alice", name);
        verify(userRepository).findNameById(1);
    }
}

class UserService {
    private final UserRepository userRepository;

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

    public String getUserName(int id) {
        return userRepository.findNameById(id);
    }
}

interface UserRepository {
    String findNameById(int id);
}
Output
Test passed successfully
โš ๏ธ

Common Pitfalls

  • Not initializing mocks with @ExtendWith(MockitoExtension.class) or MockitoAnnotations.openMocks(this) causes @InjectMocks to fail.
  • Using @InjectMocks without any @Mock dependencies results in a real instance with null dependencies.
  • Constructor injection is preferred; if multiple constructors exist, Mockito may fail to inject mocks correctly.
  • Fields not mocked or not visible (private without setters) won't be injected.
java
/* Wrong: Missing Mockito initialization */
public class WrongTest {
    @Mock
    Dependency dep;

    @InjectMocks
    Service service; // service will be null or have null dependencies

    @Test
    void test() {
        // test fails due to null pointer
    }
}

/* Right: Use MockitoExtension to initialize mocks */
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class RightTest {
    @Mock
    Dependency dep;

    @InjectMocks
    Service service; // properly injected

    @Test
    void test() {
        // test runs fine
    }
}
๐Ÿ“Š

Quick Reference

AnnotationPurpose
@MockCreates a mock object for a dependency
@InjectMocksCreates the class under test and injects mocks into it
@ExtendWith(MockitoExtension.class)Initializes mocks and injects before tests run
MockitoAnnotations.openMocks(this)Alternative to initialize mocks in setup method
โœ…

Key Takeaways

Use @InjectMocks to create the class under test and inject its @Mock dependencies automatically.
Always initialize mocks with @ExtendWith(MockitoExtension.class) or MockitoAnnotations.openMocks(this).
Constructor injection is preferred for reliable mock injection with @InjectMocks.
Without proper initialization, @InjectMocks will not inject mocks and cause NullPointerExceptions.
Use @Mock to create mock dependencies that @InjectMocks will inject into the tested class.