How do I use @Mock and @InjectMocks with JUnit?

To use @Mock and @InjectMocks with JUnit, you typically use them with Mockito.

  • @Mock creates a fake/mock dependency.
  • @InjectMocks creates the class under test and injects the mocks into it.
  • With JUnit 5, you enable Mockito using @ExtendWith(MockitoExtension.class).

1. Add Mockito dependencies

Maven

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.11.4</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>5.14.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Gradle

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.11.4'
    testImplementation 'org.mockito:mockito-junit-jupiter:5.14.2'
}

test {
    useJUnitPlatform()
}

2. Example class to test

Suppose you have a service that depends on a repository:

public class UserService {
    private final UserRepository userRepository;

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

    public String getUsernameById(Long id) {
        User user = userRepository.findById(id);

        if (user == null) {
            return "Unknown";
        }

        return user.getName();
    }
}

Repository:

public interface UserRepository {
    User findById(Long id);
}

Model:

public class User {
    private final Long id;
    private final String name;

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

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

3. Use @Mock and @InjectMocks

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;

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

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void getUsernameByIdReturnsUserNameWhenUserExists() {
        when(userRepository.findById(1L))
                .thenReturn(new User(1L, "Alice"));

        String result = userService.getUsernameById(1L);

        assertEquals("Alice", result);
    }

    @Test
    void getUsernameByIdReturnsUnknownWhenUserDoesNotExist() {
        when(userRepository.findById(99L))
                .thenReturn(null);

        String result = userService.getUsernameById(99L);

        assertEquals("Unknown", result);
    }
}

How it works

@Mock
private UserRepository userRepository;

This tells Mockito to create a mock implementation of UserRepository.

@InjectMocks
private UserService userService;

This tells Mockito to create a UserService instance and inject the mocked UserRepository into it.

Mockito tries injection in this order:

  1. Constructor injection
  2. Setter injection
  3. Field injection

Constructor injection is usually the best option because it makes dependencies explicit and easier to test.

Verifying mock interactions

You can also verify that a dependency method was called:

import static org.mockito.Mockito.verify;

@Test
void getUsernameByIdCallsRepository() {
    when(userRepository.findById(1L))
            .thenReturn(new User(1L, "Alice"));

    userService.getUsernameById(1L);

    verify(userRepository).findById(1L);
}

Common mistake: forgetting Mockito extension

If you forget this:

@ExtendWith(MockitoExtension.class)

then your @Mock fields may remain null, causing a NullPointerException.

JUnit 4 version

If you are using JUnit 4, use @RunWith(MockitoJUnitRunner.class) instead:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void getUsernameByIdReturnsUserNameWhenUserExists() {
        when(userRepository.findById(1L))
                .thenReturn(new User(1L, "Alice"));

        String result = userService.getUsernameById(1L);

        assertEquals("Alice", result);
    }
}

Quick summary

Use this pattern for JUnit 5:

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

    @Mock
    private MyRepository repository;

    @InjectMocks
    private MyService service;

    @Test
    void testSomething() {
        when(repository.findSomething()).thenReturn("value");

        String result = service.doSomething();

        assertEquals("value", result);
    }
}

Use @Mock for dependencies and @InjectMocks for the class you are testing.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.