java
CHAPTER 81 / 99
읽기 약 2분
FUNCTION
Mockito: 목 객체와 스텁
핵심 개념
@Mock·@InjectMocks·when/thenReturn·verify — Repository 목킹.
본문
Mockito 기본
import org.junit.jupiter.api.*;
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepo;
@Mock PasswordEncoder encoder;
@InjectMocks UserService userService;
@Test
void signup_success() {
// given
when(userRepo.existsByEmail("alice@example.com")).thenReturn(false);
when(encoder.encode("pass")).thenReturn("hashed");
when(userRepo.save(any(User.class)))
.thenAnswer(inv -> inv.getArgument(0));
// when
User user = userService.signup(new SignupDto("alice@example.com", "pass", "Alice"));
// then
assertEquals("alice@example.com", user.getEmail());
assertEquals("hashed", user.getPassword());
// verify — 호출 검증
verify(userRepo).existsByEmail("alice@example.com");
verify(encoder).encode("pass");
verify(userRepo).save(any(User.class));
verifyNoMoreInteractions(userRepo, encoder);
}
}ArgumentCaptor — 인자 검증
@Test
void signup_captures_user() {
when(userRepo.save(any(User.class))).thenAnswer(inv -> inv.getArgument(0));
userService.signup(new SignupDto("alice@example.com", "pass", "Alice"));
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(userRepo).save(captor.capture());
User saved = captor.getValue();
assertEquals("alice@example.com", saved.getEmail());
assertEquals("hashed", saved.getPassword());
}예외 스텁
@Test
void findById_not_found() {
when(userRepo.findById(999L)).thenReturn(Optional.empty());
assertThrows(UserNotFoundException.class,
() -> userService.findById(999L));
// 호출 횟수 검증
verify(userRepo, times(1)).findById(999L);
verify(userRepo, never()).save(any());
}
@Test
void external_api_throws() {
when(externalApi.call())
.thenThrow(new IOException("Network error"));
assertThrows(ServiceUnavailableException.class,
() -> service.callExternal());
}Mock 동작 분기
@Test
void retry_logic() {
when(api.call())
.thenThrow(new IOException("first fail"))
.thenThrow(new IOException("second fail"))
.thenReturn("success");
String result = retryService.callWithRetry();
assertEquals("success", result);
verify(api, times(3)).call();
}
// 인자별 다른 결과
when(repo.findByEmail("alice@example.com")).thenReturn(Optional.of(user1));
when(repo.findByEmail("bob@example.com")).thenReturn(Optional.of(user2));
when(repo.findByEmail(anyString())).thenReturn(Optional.empty()); // defaultSpy — 부분 mock
@Test
void spy_partial_mock() {
UserService spy = spy(new UserService(userRepo, encoder));
// 일부 메서드만 stub
doReturn(true).when(spy).isPremium(any(User.class));
// 나머지는 실제 동작
User result = spy.findById(1L); // 실제 findById 동작
assertTrue(spy.isPremium(result)); // stub 동작
}다음 챕터
CH.13 "통합 테스트: @SpringBootTest" — 풀 컨텍스트 테스트.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 Spring 코드의 Mockito 부분을 분석해서 테스트 격리·신뢰성와 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
Mockito vs 다른 패턴 비교를 실전 사례 5개로 보여주고 Mockito vs MockK vs Spock를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 코드베이스 전체를 분석해서 Mockito 관련 복잡 mock 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 기업의 Mockito 채택률과 한국 백엔드 단위 테스트 패턴를 솔직히 알려줘.
⭐ 이것만 기억하세요
Mockito: 목 객체와 스텁은 이 3가지만 확실히 잡으세요
1.@Mock으로 외부 의존성 격리 + when/thenReturn으로 동작 정의
2.verify + ArgumentCaptor로 호출 + 인자 검증 — 단위 테스트의 핵심
3.다음 챕터 CH.13에서 통합 테스트 — Spring 컨텍스트 로드
공유하기
진행도 81 / 99