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.