OPEN HYPER STEP
← 목록으로 (Java+Spring)
JAVA · 81 / 99
java
CHAPTER 81 / 99
읽기 약 2
FUNCTION

Mockito: 목 객체와 스텁


핵심 개념

@Mock·@InjectMocks·when/thenReturn·verify — Repository 목킹.

본문

Mockito 기본

JAVA📋 코드 (35줄)
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 — 인자 검증

JAVA📋 코드 (13줄)
@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());
}

예외 스텁

JAVA📋 코드 (21줄)
@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 동작 분기

JAVA📋 코드 (17줄)
@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());  // default

Spy — 부분 mock

JAVA📋 코드 (11줄)
@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