How do I verify method calls with Mockito and JUnit?

To verify method calls with Mockito and JUnit, use Mockito’s verify() method. This lets you check whether a mocked dependency method was called, how many times it was called, and what arguments were passed.

1. Basic Example

Suppose you have a service that depends on a repository.

public interface UserRepository {
    void save(User user);
}
public class UserService {
    private final UserRepository userRepository;

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

    public void register(User user) {
        userRepository.save(user);
    }
}

You can verify that save() was called:

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class UserServiceTest {

    @Test
    void register_shouldSaveUser() {
        UserRepository userRepository = mock(UserRepository.class);
        UserService userService = new UserService(userRepository);

        User user = new User();

        userService.register(user);

        verify(userRepository).save(user);
    }
}

The important line is:

verify(userRepository).save(user);

This means: “After running the test, confirm that save(user) was called on userRepository.”

2. Verifying Number of Calls

By default, verify() expects the method to be called exactly once.

These two lines are equivalent:

verify(userRepository).save(user);
verify(userRepository, times(1)).save(user);

You can verify different call counts:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

verify(userRepository, times(1)).save(user);
verify(userRepository, times(2)).save(user);
verify(userRepository, never()).delete(user);

Common options include:

verify(mock, times(1)).method();
verify(mock, never()).method();
verify(mock, atLeastOnce()).method();
verify(mock, atLeast(2)).method();
verify(mock, atMost(3)).method();

Example:

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class NotificationServiceTest {

    @Test
    void sendWelcomeEmail_shouldNotifyUser() {
        EmailSender emailSender = mock(EmailSender.class);
        NotificationService notificationService = new NotificationService(emailSender);

        notificationService.sendWelcomeEmail("[email protected]");

        verify(emailSender, atLeastOnce()).send("[email protected]", "Welcome!");
    }
}

3. Verifying Arguments with Matchers

If you do not want to match the exact object, you can use argument matchers.

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

verify(userRepository).save(any(User.class));

For specific values:

verify(emailSender).send(eq("[email protected]"), eq("Welcome!"));

You can also mix broad and specific matching:

verify(emailSender).send(eq("[email protected]"), any(String.class));

Important: if you use matchers for one argument, use matchers for all arguments in that method call.

Correct:

verify(emailSender).send(eq("[email protected]"), any(String.class));

Avoid mixing raw values and matchers:

verify(emailSender).send("[email protected]", any(String.class));

4. Verifying No Calls

To verify that a mock had no interactions:

import static org.mockito.Mockito.verifyNoInteractions;

verifyNoInteractions(userRepository);

To verify that no more calls happened after the expected ones:

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

verify(userRepository).save(user);
verifyNoMoreInteractions(userRepository);

Example:

@Test
void register_invalidUser_shouldNotSaveUser() {
    UserRepository userRepository = mock(UserRepository.class);
    UserService userService = new UserService(userRepository);

    User invalidUser = new User();

    userService.register(invalidUser);

    verifyNoInteractions(userRepository);
}

5. Verifying Order of Calls

Use InOrder when the order matters.

import org.junit.jupiter.api.Test;
import org.mockito.InOrder;

import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;

class OrderServiceTest {

    @Test
    void processOrder_shouldCallMethodsInOrder() {
        PaymentService paymentService = mock(PaymentService.class);
        InventoryService inventoryService = mock(InventoryService.class);

        OrderService orderService = new OrderService(paymentService, inventoryService);

        Order order = new Order();

        orderService.process(order);

        InOrder inOrder = inOrder(inventoryService, paymentService);

        inOrder.verify(inventoryService).reserve(order);
        inOrder.verify(paymentService).charge(order);
    }
}

6. Using @Mock with JUnit 5

Instead of manually creating mocks with mock(), you can use Mockito’s JUnit 5 extension.

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.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void register_shouldSaveUser() {
        User user = new User();

        userService.register(user);

        verify(userRepository).save(user);
    }
}

Here:

@Mock
private UserRepository userRepository;

creates a mock repository.

@InjectMocks
private UserService userService;

creates the service and injects the mock into it.

7. Capturing Arguments with ArgumentCaptor

Use ArgumentCaptor when you want to inspect the object passed to a method.

import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

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

class UserServiceTest {

    @Test
    void register_shouldSaveUserWithExpectedName() {
        UserRepository userRepository = mock(UserRepository.class);
        UserService userService = new UserService(userRepository);

        userService.register("Alice");

        ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);

        verify(userRepository).save(userCaptor.capture());

        User savedUser = userCaptor.getValue();

        assertEquals("Alice", savedUser.getName());
    }
}

This is useful when the method under test creates a new object internally, so you cannot verify using the exact same instance.

8. Verifying Exceptions Still Triggers Calls

You can combine JUnit assertions with Mockito verification.

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class PaymentServiceTest {

    @Test
    void pay_invalidAmount_shouldLogFailure() {
        AuditLogger auditLogger = mock(AuditLogger.class);
        PaymentService paymentService = new PaymentService(auditLogger);

        assertThrows(IllegalArgumentException.class, () -> {
            paymentService.pay(-10);
        });

        verify(auditLogger).log("Invalid payment amount: -10");
    }
}

9. Maven Dependencies

For JUnit 5 and Mockito, add dependencies like these:

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

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

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

10. Gradle Dependencies

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
    testImplementation 'org.mockito:mockito-core:5.18.0'
    testImplementation 'org.mockito:mockito-junit-jupiter:5.18.0'

    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

test {
    useJUnitPlatform()
}

Common Verification Patterns

verify(repository).save(user);
verify(repository, times(1)).save(user);
verify(repository, never()).delete(user);
verify(repository, atLeastOnce()).save(any(User.class));
verify(repository, atMost(3)).findByEmail(any(String.class));
verifyNoInteractions(repository);
verifyNoMoreInteractions(repository);

Summary

Use Mockito’s verify() when you want to test interactions between objects.

Typical usage:

verify(mock).method(argument);

For example:

verify(userRepository).save(user);

Use verification when the important result of a method is not just a returned value, but that another dependency was called correctly.

How do I mock dependencies in unit tests?

To mock dependencies in unit tests, you usually use a mocking framework such as Mockito. Mocking lets you test one class in isolation without running the real logic of its collaborators.

Basic Mockito Example

Suppose you have a service that depends on another class:

@Service
public class MyService {

    private final MyDependency dependency;

    public MyService(MyDependency dependency) {
        this.dependency = dependency;
    }

    public void process() {
        dependency.doSomething();
    }
}

You can mock MyDependency in a unit test like this:

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.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

    @Mock
    private MyDependency dependency;

    @InjectMocks
    private MyService myService;

    @Test
    void processCallsDependency() {
        myService.process();

        verify(dependency).doSomething();
    }
}

What the annotations mean

  • @Mock creates a mock object.
  • @InjectMocks creates the class under test and injects the mocks into it.
  • @ExtendWith(MockitoExtension.class) enables Mockito support in JUnit 5.
  • verify(...) checks that a method was called.

Mocking return values

If the dependency returns a value, use when(...).thenReturn(...):

import static org.mockito.Mockito.when;

when(repository.findNameById(1L)).thenReturn("Alice");

Example:

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

    String result = userService.getUserName(1L);

    assertEquals("Alice", result);
}

Mocking exceptions

You can also make a mock throw an exception:

import static org.mockito.Mockito.when;

when(repository.findById(99L))
        .thenThrow(new EntityNotFoundException("User not found"));

For void methods, use doThrow(...):

import static org.mockito.Mockito.doThrow;

doThrow(new RuntimeException("Failure"))
        .when(dependency)
        .doSomething();

Verifying interactions

You can verify how your class interacted with its dependencies:

verify(dependency).doSomething();
verify(dependency, times(1)).doSomething();
verify(dependency, never()).doSomething();

Spring Boot unit test example

For a pure unit test, prefer Mockito without starting the Spring context:

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

    @Mock
    private MyDependency dependency;

    @InjectMocks
    private MyService service;

    @Test
    void processCallsDependency() {
        service.process();

        verify(dependency).doSomething();
    }
}

Spring integration-style test

If you need the Spring context, use Spring’s test support and replace a bean with a mock:

@SpringBootTest
class MyServiceSpringTest {

    @MockitoBean
    private MyDependency dependency;

    @Autowired
    private MyService service;

    @Test
    void processCallsDependency() {
        service.process();

        verify(dependency).doSomething();
    }
}

Use this style when you want to test Spring wiring, configuration, transactions, security, or other framework behavior.

Rule of thumb

  • Use Mockito @Mock + @InjectMocks for fast unit tests.
  • Use Spring test annotations only when you need the Spring application context.
  • Mock external systems such as databases, APIs, message queues, and file systems.
  • Avoid mocking simple value objects or the class you are actually testing.

How do I use Mockito with JUnit?

To use Mockito with JUnit, you add Mockito to your test dependencies, enable Mockito in your JUnit test class, then create mocks and define their behavior.

Below is a simple JUnit 5 + Mockito example.

1. Add Dependencies

Maven

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

    <!-- Mockito Core -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.14.2</version>
        <scope>test</scope>
    </dependency>

    <!-- Mockito integration for JUnit 5 -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>5.14.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Make sure your Maven Surefire plugin supports JUnit 5:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.5.2</version>
        </plugin>
    </plugins>
</build>

Gradle

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.11.4'
    testImplementation 'org.mockito:mockito-core:5.14.2'
    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 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;
    }
}
import java.util.Optional;

public interface UserRepository {
    Optional<User> findById(Long id);
}
public class UserService {
    private final UserRepository userRepository;

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

    public String getUserName(Long id) {
        return userRepository.findById(id)
                .map(User::getName)
                .orElse("Unknown User");
    }
}

3. Write a Mockito Test with JUnit 5

Use @ExtendWith(MockitoExtension.class) to enable Mockito support.

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 java.util.Optional;

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

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void shouldReturnUserNameWhenUserExists() {
        User user = new User(1L, "Alice");

        when(userRepository.findById(1L))
                .thenReturn(Optional.of(user));

        String result = userService.getUserName(1L);

        assertEquals("Alice", result);
        verify(userRepository).findById(1L);
    }

    @Test
    void shouldReturnUnknownUserWhenUserDoesNotExist() {
        when(userRepository.findById(99L))
                .thenReturn(Optional.empty());

        String result = userService.getUserName(99L);

        assertEquals("Unknown User", result);
        verify(userRepository).findById(99L);
    }
}

4. What the Mockito Annotations Mean

Annotation Purpose
@Mock Creates a mock object
@InjectMocks Creates the class under test and injects mocks into it
@ExtendWith(MockitoExtension.class) Enables Mockito support in JUnit 5

5. Common Mockito Methods

when(...).thenReturn(...)

Used to define mock behavior.

when(userRepository.findById(1L))
        .thenReturn(Optional.of(new User(1L, "Alice")));

verify(...)

Used to check whether a method was called.

verify(userRepository).findById(1L);

verify(..., times(...))

Used to check how many times a method was called.

verify(userRepository, times(1)).findById(1L);

You need this static import:

import static org.mockito.Mockito.times;

6. Mockito Without Annotations

You can also create mocks manually.

import org.junit.jupiter.api.Test;

import java.util.Optional;

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

class UserServiceManualMockTest {

    @Test
    void shouldReturnUserName() {
        UserRepository userRepository = mock(UserRepository.class);
        UserService userService = new UserService(userRepository);

        when(userRepository.findById(1L))
                .thenReturn(Optional.of(new User(1L, "Alice")));

        String result = userService.getUserName(1L);

        assertEquals("Alice", result);
    }
}

7. Typical Mockito Test Structure

A clean Mockito test usually follows the Arrange, Act, Assert pattern:

@Test
void shouldReturnUserName() {
    // Arrange
    User user = new User(1L, "Alice");
    when(userRepository.findById(1L)).thenReturn(Optional.of(user));

    // Act
    String result = userService.getUserName(1L);

    // Assert
    assertEquals("Alice", result);
    verify(userRepository).findById(1L);
}

Summary

To use Mockito with JUnit 5:

  1. Add mockito-core and mockito-junit-jupiter.
  2. Add @ExtendWith(MockitoExtension.class) to your test class.
  3. Use @Mock for dependencies.
  4. Use @InjectMocks for the class being tested.
  5. Use when(...).thenReturn(...) to define behavior.
  6. Use verify(...) to check interactions.

How do I write unit tests for Spring components?

Writing Unit Tests for Spring Components

For Spring components, you usually want to test business logic without starting the full Spring application context. That means using JUnit 5 and Mockito for most unit tests.

Use Spring’s test support only when you need Spring-specific behavior such as dependency injection, MVC request handling, configuration binding, or persistence integration.


1. Unit Test a Spring @Service

Example service:

package com.example.order;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;

    public Order createOrder(String customerEmail) {
        if (customerEmail == null || customerEmail.isBlank()) {
            throw new IllegalArgumentException("Customer email is required");
        }

        Order order = new Order(customerEmail);
        return orderRepository.save(order);
    }
}

Unit test:

package com.example.order;

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.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OrderServiceTest {

    @Mock
    private OrderRepository orderRepository;

    @InjectMocks
    private OrderService orderService;

    @Test
    void createOrderSavesOrder() {
        Order savedOrder = new Order("[email protected]");

        when(orderRepository.save(any(Order.class))).thenReturn(savedOrder);

        Order result = orderService.createOrder("[email protected]");

        assertEquals("[email protected]", result.getCustomerEmail());
        verify(orderRepository).save(any(Order.class));
    }

    @Test
    void createOrderRejectsBlankEmail() {
        IllegalArgumentException exception = assertThrows(
                IllegalArgumentException.class,
                () -> orderService.createOrder(" ")
        );

        assertEquals("Customer email is required", exception.getMessage());
    }
}

This is a true unit test because no Spring context is started.


2. Unit Test a Spring @Component

Example component:

package com.example.notification;

import org.springframework.stereotype.Component;

@Component
public class EmailValidator {

    public boolean isValid(String email) {
        return email != null && email.contains("@");
    }
}

Test:

package com.example.notification;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class EmailValidatorTest {

    private final EmailValidator emailValidator = new EmailValidator();

    @Test
    void returnsTrueForValidEmail() {
        assertTrue(emailValidator.isValid("[email protected]"));
    }

    @Test
    void returnsFalseForInvalidEmail() {
        assertFalse(emailValidator.isValid("invalid-email"));
        assertFalse(emailValidator.isValid(null));
    }
}

If a component has no dependencies, just instantiate it directly.


3. Unit Test a Spring MVC @Controller

For controllers, use @WebMvcTest. This loads only the MVC layer, not the whole application.

Example controller:

package com.example.order;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class OrderController {

    private final OrderService orderService;

    @GetMapping("/orders/{id}")
    public OrderResponse getOrder(@PathVariable Long id) {
        return orderService.getOrder(id);
    }
}

Controller test:

package com.example.order;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(OrderController.class)
class OrderControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockitoBean
    private OrderService orderService;

    @Test
    void getOrderReturnsOrder() throws Exception {
        when(orderService.getOrder(1L))
                .thenReturn(new OrderResponse(1L, "[email protected]"));

        mockMvc.perform(get("/orders/1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1L))
                .andExpect(jsonPath("$.customerEmail").value("[email protected]"));
    }
}

In newer Spring Boot versions, prefer @MockitoBean over the older @MockBean.


4. Unit Test Repository-Using Services

If your service depends on a Spring Data JPA repository, mock the repository in a unit test.

package com.example.user;

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 java.util.Optional;

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 findUserReturnsUser() {
        User user = new User(1L, "[email protected]");

        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        User result = userService.findUser(1L);

        assertEquals("[email protected]", result.getEmail());
    }
}

Do not use a real database for a unit test. If you want to test repository mappings or queries, use an integration/slice test such as @DataJpaTest.


5. Test Spring Data JPA Repositories with @DataJpaTest

This is not a pure unit test, but it is the standard way to test repositories.

package com.example.user;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

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

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void findByEmailReturnsUser() {
        User user = new User();
        user.setEmail("[email protected]");

        userRepository.save(user);

        Optional<User> result = userRepository.findByEmail("[email protected]");

        assertTrue(result.isPresent());
    }
}

Use this when you want to verify:

  • JPA mappings
  • repository query methods
  • custom JPQL/native queries
  • database constraints

6. Recommended Dependencies

For Maven, the common Spring Boot test starter is usually enough:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

It includes commonly used testing libraries such as:

  • JUnit Jupiter
  • AssertJ
  • Mockito
  • Spring Test
  • MockMvc support

7. Common Testing Patterns

Arrange, Act, Assert

@Test
void methodNameExpectedBehavior() {
    // Arrange
    when(repository.findById(1L)).thenReturn(Optional.of(entity));

    // Act
    Result result = service.doSomething(1L);

    // Assert
    assertEquals(expectedValue, result.value());
}

Verify interactions only when meaningful

verify(repository).save(any(Order.class));

Avoid verifying every single method call. Prefer verifying observable behavior.

Test exceptions

@Test
void throwsExceptionWhenUserNotFound() {
    assertThrows(
            UserNotFoundException.class,
            () -> userService.findUser(999L)
    );
}

8. Choosing the Right Test Type

Component Recommended test style
Plain utility/component Instantiate directly
@Service with dependencies JUnit 5 + Mockito
@Controller @WebMvcTest + MockMvc
Repository @DataJpaTest
Full application flow @SpringBootTest

Rule of Thumb

Use the smallest test scope that proves the behavior:

  • Business logic: plain JUnit + Mockito
  • Web layer: @WebMvcTest
  • Persistence layer: @DataJpaTest
  • End-to-end Spring wiring: @SpringBootTest

Most Spring component unit tests should not need @SpringBootTest.