Mock은 진짜 객체의 행동을 흉내 내는 가짜 객체입니다.
주로 다음과 같은 상황에서 사용됩니다.
상황 | Mock을 쓰는 게 좋다 | Mock 없이 직접 테스트 |
---|---|---|
외부 시스템 연동 | ✅ | ❌ |
DB 등 I/O 테스트 | ✅ | ❌ (속도 ↓) |
비즈니스 로직 검증 | ❌ (실제 객체 추천) | ✅ |
복잡한 의존성 존재 | ✅ | ❌ |
💡 Mock은 테스트를 빠르고 단위화할 수 있지만,
모든 것을 Mock으로 대체하면 실제 동작과 괴리가 생길 수 있습니다.
public class AuthService {
private final UserRepository userRepository;
public AuthService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public boolean login(String email, String password) {
User user = userRepository.findByEmail(email);
return user != null && user.getPassword().equals(password);
}
}
@ExtendWith(MockitoExtension.class)
class AuthServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private AuthService authService;
@Test
void 로그인_성공() {
// given
User mockUser = new User("test@email.com", "1234");
given(userRepository.findByEmail("test@email.com")).willReturn(mockUser);
// when
boolean result = authService.login("test@email.com", "1234");
// then
assertTrue(result);
verify(userRepository).findByEmail(any());
}
}
✅ 여기서 UserRepository
는 실제 DB 접근하는 객체지만, 우리는 Mock 객체로 동작을 흉내 냈습니다. 테스트는 빠르고, 실제 DB 없이도 동작 가능하게 됬습니다!
테스트가 많아질수록 @BeforeEach
등을 활용해서 Mock 설정을 공통 처리해두면 유지보수하기 편합니다.
@BeforeEach
void setUp() {
given(userRepository.findByEmail(anyString()))
.willReturn(new User("user@test.com", "pass"));
}
Mock을 활용하면 예외 상황이나 실패 케이스도 손쉽게 시뮬레이션할 수 있습니다.
@Test
void 로그인_실패_비밀번호_불일치() {
User mockUser = new User("user@test.com", "correct");
given(userRepository.findByEmail("user@test.com")).willReturn(mockUser);
boolean result = authService.login("user@test.com", "wrong");
assertFalse(result);
}
verify(userRepository, times(1)).findByEmail("user@test.com");
Mock은 테스트의 강력한 도구지만, 언제 어떻게 쓸지 고민하지 않으면 테스트 신뢰도를 떨어뜨릴 수 있습니다.
👉 이제부터 테스트 코드에 Mock를 활용하여 신뢰도 있는 테스트 코드를 작성해 보아요!