서론
본 포스팅은 아래의 인강을 듣고, 추가 공부가 필요한 내용들을 포함하여 정리한 포스팅입니다.
Mock
사전적인 뜻은 모조품, 가짜 라는 뜻을 가지고 있으며, 테스트 진행 시 진행하고자 하는 실제 객체와 동일한 가짜 객체(Mock)를 만들어서 사용한다.
언제 사용해야 할까?
- 테스트 작성 환경 구축이 어려울때
- 특정 경우에 의존적일때
- 테스트 시간이 오래걸릴 때
Mock과 Stub
자주 사용되는 Mock과 Stub은 가짜 객체이고, 요청한 것에 대한 어떤 반환 값을 받아볼 수 있다는 점에서는 비슷하여 혼동하기 쉽다. 두 개념에 대해 마틴 파울러의 의견을 담은 게시물을 가져왔다. 참고 해보면 좋을 것 같다.
Stub은 상태 검증에 초점이 맞춰져있다. 테스트에서 요청한 것에 대한 미리 준비된 결과를 제공하는 객체로써, 그 외에는 응답하지 않는다. 외부 의존성을 가진 코드의 테스트에 주로 사용된다.
Mock은 행위 검증이 중심이다. 행위에 대한 기대값을 작성하고, 그에 따라 동작하도록 만들어진 객체이다. 특정 메서드의 호출 여부와 매개변수 등을 확인하는 등 더 많은 기능을 제공한다.
Framework 종류
1. EasyMock
- https://easymock.org/
- 가장 오래된 Mock Framework
- EasyMook Class Extention이라는 기능을 통해 구현 클래스를 통해 객체를 생성한다.
진행 순서
CreateMock : 인터페이스에 해당하는 Mock 객체 생성
Record : Mock 객체 메서드의 예상 동작을 녹화
Replay : 예정된 상태로 재생한다.
Verify : 행위가 발생했는지 검증한다.
2. jMock
- http://jmock.org/
- 가독성이 좋은 프레임워크로 연쇄호출이 특징이다.
- Hamcrest Macher 라이브러리를 사용한다.
진행 순서
CreateMock : 인터페이스에 해당하는 Mock 객체 생성
Expect : 예상 동작을 미리 지정
Excercise : 테스트 메서드 내에서 Mock 객체 사용
Verify : 검증 (프레임워크가 직접 판단)
3. Mockito
- https://site.mockito.org/
- 사용법이 단순하여 테스트 자체에 집중할 수 있다.
- 리팩토링이 쉽고 API가 단순하다.
- 테스트 스텁을 만들기 쉽고, 스텁을 만드는 것과 검증을 분리한다.
- 실패 시 발생하는 스택 트레이스가 깔끔하다.
진행 순서
CreateMock : 인터페이스에 해당하는 Mock 객체 생성
Stub : 예상 동작 지정
Excercise : 테스트 메서드 내에서 Mock 객체 사용
Verify : 검증 (프레임워크가 직접 판단)
테스트 더블(Test Double)
Mock의 상위 개념으로, 테스트하려는 객체와 연관된 객체를 사용하기가 어려울 때, 실제 객체의 일부 기능을 대신하는 대체 구현된 객체를 말한다. 용어의 출처는 스턴트맨에서 왔다고 한다. 스턴트맨을 영어로는 Stunt Double이라고 하며 여기서 차용된 용어라고 한다.
- 테스트를 진행하기 어려운 경우 이를 대신해 테스트를 진행할 수 있도록 만들어주는 객체
- Mock 객체와 유사하지만 테스트 더블이 상위의 의미로 사용됨
테스트 더블은 목적에 따라 아래의 유형별로 분류될 수 있다.
더미 객체(Dummy Object)
- 인스턴스화 될 수 있는 수준으로 객체를 구현하며 객체의 기능은 필요하지 않은 경우 사용
- 아무것도 하지 않는 허수아비
페이크 객체(Fake Object)
- 실제 로직이 구현된 것처럼 보이는 객체
- 다른 객체들과의 의존성을 제거하기 위해 사용
- 적절한 수준에서 구현하거나, Mock 프레임워크를 사용한다.
- 페이크 객체 생성을 위한 시간 등의 소요가 클 경우, 실제 객체를 가져와 테스트한다.
- 단순 형태로 동일한 기능은 수행하지만, 프로덕션에서 쓰기에는 부족한 객체(ex : FakeRepository)
map으로 단순 구현이 가능하다.
Repository.save를 실행했을 경우 해당 객체를 put하고
Repository.findById를 실행했을 경우 Key 기반으로 Value를 return해주는 등의 형태를 취할 수 있음.
테스트 스텁(Test Stub)
- 실제로 동작하는 것처럼 보이게 만들어 놓은 객체로 더미 객체보다 조금 더 구현된 객체
- 특정 상태를 가정해 특정 값이나 메세지를 리턴해주는 작업을 한다.
- 특정 상태를 가정해서 하드코딩된 형태로 로직에 따른 값의 변경을 테스트하는 것이 불가능하다.
테스트 스파이(Test Spy)
- 테스트에 사용되는 객체, 메서드의 사용 여부 및 정상 호출 여부를 기록하고 보여준다.
- 테스트 더블로 구현된 객체에 자기 자신이 호출되었을 때 확인이 필요한 부분을 기록하도록 구현한다.
- 호출 횟수가 필요한 경우 전역 변수로 설정하여 로직을 메서드화하여 특정 테스트에서 호출한다.
- 행위 기반 테스트가 필요한 경우 사용
Mock 객체(Mock Object)
- 행위를 검증하기 위해 사용되는 객체로 프레임워크로 만들 수도 있다.
- 테스트 더블의 하위 객체로의 좁은 의미와, 테스트 더블을 포함한 넓은 의미 두 가지로 사용될 수 있다.
- 행위 검증은 복잡도나 정확성 등 작성하기 어려운 부분이 많기 때문에 상태 검증은 가능하다면 만들지 않는다.
References
관련 포스팅
테스트 코드를 작성하는 이유 - TestCode (1)
JUnit 5를 사용한 Java 단위 테스트 - TestCode (3)
2023.04 ~ 백엔드 개발자의 기록
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!