[JAVA] Mock and test Autowired classes (MockitoExtension, initMocks)

At the time of UT (unit test), you can use @Mock to Mock an Autowired class and decide its behavior freely. With @Mock, you can focus on the classes you want to test, independent of the outside world. You have to use Mockito Extension or initMocks because you need magic when using @Mock.

Maven Add Dependency to pom.xml to use MockitoExtension.

initMocks

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor //Autowired God Repository without using a constructor
public class GodServiceImpl implements GodService {

  private final GodRepository godRepository; //Final when using RequiredArgsConstructor

  @Override
  public void update(List updateList) {
    godRepository.update(updateList);
  }
}

When using initMocks in the test of

import static java.util.Arrays.asList;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

class GodServiceImplTest {

  @InjectMocks //Classes using Mocked classes
  private GodServiceImpl godServiceImpl;

  @Mock //The class you want to mock
  private GodRepository godRepository;

  @BeforeEach
  public void setUp() {
    initMocks(this); //Magic
  }

  @Test
  void update() {
    List<String> updateList = asList("a", "b", "c", "d");
    when(godRepository.update(updateList)).thenReturn(4);

    godServiceImpl.update(updateList);

    verify(godRepository).update(updateList);
  }
}

It looks like you're initializing a Mock object with initMocks ...

MockitoExtension With Mockito Extension

import static java.util.Arrays.asList;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class) //Magic
class GodServiceImplTest {

  private GodService godService;

  @Mock //The class you want to mock
  private GodRepository godRepository;

  @BeforeEach
  public void setUp() {
    godService = new GodServiceImpl(godRepository); //Inject the Mocked God Repository
  }

  @Test
  void update() {
    List<String> updateList = asList("a", "b", "c", "d");
    when(godRepository.update(updateList)).thenReturn(4);

    godService.update(updateList);

    verify(godRepository).update(updateList);
  }
}

Just by Mocking, you can't tell which class you want to Mock, so you need to pass it as an argument.

MockitoExtension + InjectMocks You can also combine Mockito Extension and Inject Mocks.

import static java.util.Arrays.asList;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.List;
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) //Magic
class GodServiceImplTest {

  @InjectMocks //Classes using Mocked classes
  private GodServiceImpl godServiceImpl;

  @Mock //The class you want to mock
  private GodRepository godRepository;

  @Test
  void update() {
    List<String> updateList = asList("a", "b", "c", "d");
    when(godRepository.update(updateList)).thenReturn(4);

    godServiceImpl.update(updateList);

    verify(godRepository).update(updateList);
  }
}

You no longer have to inject Mock objects with Before Each.

Recommended Posts

Mock and test Autowired classes (MockitoExtension, initMocks)
Classes and instances
[Ruby] Classes and instances
HashMap and HashSet classes
About classes and instances
Mock test de Mockito
Ruby classes and instances
List and happy classes
java (classes and instances)