Mock Object
Mock Object
개요
Mock Object(목 오브젝트)는 소프트어 테스트, 특히 단위 테스트(Unit Testing)에서 외부 의존성을 제어하기 위해 사용되는 가짜 객체. 실제 객체를신하여 테스트 환에서 동작하며, 시템의 특정 부분이 예상대로 작하는지 검증하는 데 중요한 역할을 합니다. Mock Object는 외부 시스템(예: 데이터베이스, 웹 서비스, 파일 시스템 등)에 의존하는 코드를 테스트할 때 실제 의존성을 사용하지 않고도 테스트를 수행할 수 있도록 해줍니다.
Mock Object는 테스트의 신뢰성, 속도, 재현성을 높이며, 테스트 대상 코드의 로직만을 집중적으로 검증할 수 있게 합니다. 이는 소프트웨어 개발 과정에서 버그를 조기에 발견하고, 코드의 유지보수성을 향상시키는 데 기여합니다.
Mock Object의 목적
Mock Object는 다음과 같은 주요 목적을 가지고 사용됩니다:
1. 외부 의존성의 격리
테스트 대상 코드가 데이터베이스, 외부 API, 네트워크 등 외부 리소스에 의존할 경우, 이러한 요소들은 테스트의 속도를 느리게 하거나 결과의 불확실성을 초래할 수 있습니다. Mock Object를 사용하면 이러한 외부 요소를 가짜로 대체하여, 테스트가 오직 로직 자체에 집중할 수 있도록 합니다.
2. 예측 가능한 테스트 환경 제공
실제 외부 시스템은 네트워크 지연, 인증 실패, 서비스 다운 등의 이유로 불안정할 수 있습니다. Mock Object는 예측 가능한 응답을 반환하도록 설정할 수 있어, 테스트의 일관성과 재현성을 보장합니다.
3. 특정 시나리오 시뮬레이션
예외 처리, 에러 응답 특정 상태 변화 등 실제 시스템에서는 재현하기 어려운 상황을 Mock Object로 쉽게 시뮬레이션할 수 있습니다. 예를 들어, API가 500 에러를 반환하는 상황을 가정하여 오류 처리 로직을 테스트할 수 있습니다.
Mock Object와 유사 개념 비교
Mock Object는 비슷한 개념인 Stub, Fake, Spy와 혼동될 수 있으나, 각각의 용도와 특성이 다릅니다.
| 개념 | 설명 | 사용 목적 |
|---|---|---|
| Mock Object | 메서드 호출 여부, 호출 순서, 인자 등을 검증할 수 있는 행동 중심의 가짜 객체 | 테스트 대상이 의존 객체를 올바르게 사용했는지 검증 |
| Stub | 미리 정의된 값을 반환하는 상태 중심의 간단한 가짜 객체 | 외부 의존성의 결과를 고정하여 테스트 진행 |
| Fake | 실제 로직을 간소화한 형태로 구현한 객체 (예: 인메모리 데이터베이스) | 실제 시스템을 대체하되, 가벼운 동작을 제공 |
| Spy | 실제 객체를 감싸서 호출 내역을 기록하는 객체 | 메서드가 몇 번 호출되었는지, 어떤 인자로 호출되었는지 추적 |
예를 들어, 사용자 정보를 가져오는 UserService가 [UserRepository](/doc/%EA%B8%B0%EC%88%A0/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EA%B0%9C%EB%B0%9C/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EC%84%A4%EA%B3%84/UserRepository)에 의존할 때:
- Stub은 항상 "홍길동"을 반환하도록 설정.
- Mock은 userRepository.[findById](/doc/%EA%B8%B0%EC%88%A0/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4%20%EA%B0%9C%EB%B0%9C/%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%A0%91%EA%B7%BC/findById)()가 정확히 한 번 호출되었는지 검증.
- Fake는 실제 DB 대신 메모리에 사용자 데이터를 저장하고 조회.
Mock Object의 작동 원리
Mock Object는 일반적으로 프레임워크를 통해 생성됩니다. 대표적인 도구로는 Java의 Mockito, Python의 unittest.mock, JavaScript의 Jest, C#의 Moq 등이 있습니다.
예시 (Java + Mockito)
// 테스트 대상 클래스
public class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUserName(Long id) {
User user = userRepository.findById(id);
return user != null ? user.getName() : "Unknown";
}
}
// 단위 테스트에서 Mock 사용
@Test
public void testGetUserName() {
// UserRepository의 Mock 객체 생성
UserRepository mockRepo = Mockito.mock(UserRepository.class);
User mockUser = new User("홍길동");
// Mock의 동작 정의
Mockito.when(mockRepo.findById(1L)).thenReturn(mockUser);
// 테스트 대상 객체 생성
UserService service = new UserService(mockRepo);
// 테스트 실행
String name = service.getUserName(1L);
// 검증
assertEquals("홍길동", name);
Mockito.verify(mockRepo).findById(1L); // 메서드 호출 여부 검증
}
이 예제에서 mockRepo는 실제 데이터베이스에 접근하지 않지만, findById() 메서드가 호출되었을 때 원하는 값을 반환하도록 설정됩니다. 또한, verify()를 통해 해당 메서드가 정확히 한 번 호출되었는지 확인할 수 있습니다.
사용 시 고려 사항
장점
- 테스트 속도 향상 (외부 I/O 제거)
- 테스트의 독립성과 재현성 확보
- 다양한 에러 시나리오 시뮬레이션 가능
단점 및 주의점
- 과도한 Mock 사용은 테스트가 실제 통합 환경과 동떨어지게 만들 수 있음
- Mock이 실제 객체와 동작이 다를 경우 거짓 긍정(false positive) 발생 가능
- Mock 설정이 복잡해질 수 있어 테스트 코드의 가독성 저하
따라서 단위 테스트에는 Mock을 적절히 사용하되, 통합 테스트나 E2E 테스트에서는 실제 의존성을 사용하는 것이 바람직합니다.
관련 도구 및 프레임워크
| 언어 | 주요 Mock 프레임워크 |
|---|---|
| Java | Mockito, EasyMock, JMock |
| Python | unittest.mock, pytest-mock |
| JavaScript/TypeScript | Jest, Sinon.js |
| C# | Moq, NSubstitute |
| Ruby | RSpec Mocks |
이러한 도구들은 Mock 객체 생성, 메서드 호출 기록, 인자 검증, 예외 발생 시뮬레이션 등을 쉽게 수행할 수 있도록 도와줍니다.
참고 자료
- Fowler, Martin. "Mocks Aren't Stubs." martinfowler.com, 2007.
https://martinfowler.com/articles/mocksArentStubs.html - Mockito 공식 문서: https://site.mockito.org
- Jest 공식 문서: https://jestjs.io
Mock Object는 현대 소프트웨어 개발에서 테스트 주도 개발(TDD)과 지속적 통합(CI)을 가능하게 하는 핵심 기술 중 하나입니다. 올바르게 사용할 경우 코드 품질을 크게 향상시킬 수 있으며, 개발자의 신뢰성 있는 테스트 환경을 구축하는 데 필수적인 요소입니다.
이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.