-
Service Layer의 단위테스트 작성 : (2) Fake 객체Spring 2022. 2. 3. 17:11
https://dodop-blog.tistory.com/285
https://dodop-blog.tistory.com/286
이전에 @MockBean을 이용하여 ServiceLayer의 테스트 코드를 작성하는 방법을 배웠다.
그런데 해당 어노테이션을 사용하여 테스트를 진행하고 Mock객체를 이용하여 단위테스트 진행 시,
Stub의 .thenReturn 객체 필드의 변화를 감지하지 못하는 단점이 있다는 코드리뷰를 받게 되었다.
Mock 객체 사용의 단점을 알아보고 이를 해결하기 위한 방안인 Fake객체의 작성 방법을 알아보자.
Mock 객체의 단점 ① .thenReturn 객체의 상태변화 감지 불가
Mock 객체의 when 메소드 또는 given 메소드로 행위를 설정할 때 협력객체의 실제 구현체가 그렇게 구현된다는 가정하에 작성하게 되지만 이는 구현체의 정상 작동 여부를 보장하지는 않는다.
Mock 객체의 단점 ① 리팩토링 진행시 테스트 코드 수정 필요
Mock 객체를 사용하여 테스트 코드를 작성하게 된다면 when, given 메소드를 사용하여 Mock객체의 반응을 모두 설정해주어야 하기 때문에, 만약 테스트 대상 메소드의 리팩토링이 진행된다면 테스트 코드 또한 대상 메소드에 맞추어 리팩토링이 이루어져야 한다. 이는 메서드를 사용하는 대상이 내부 메서드 진행방식을 알아야 테스트 코드가 정상적으로 진행된다는 의미이다.
해결방안
실제 구현체를 테스트 코드에 넣게 된다면 네트워크나 데이터베이스에 접근하기 되는 경우 소요시간이 길어지고 네트워크의 문제 등의 외부요인으로 테스트 코드가 실패하게 될 수 있다. 따라서 Production에 사용되는 실제 구현체가 아닌 네트워크나 데이터베이스와 소통하지 않고 Production에 사용되지 않는 Fake객체 구현체를 만들어 사용 하도록 한다.
FakeRepository
public class FakeActivityRepository implements ActivityRepository { private Map<String, Activity> activities = new HashMap<>(); private Integer lastActivityId = 0; public FakeActivityRepository() { } @Override public Activity findByActivityId(Integer id) { Activity activity = activities.get(id); if(activity == null){ throw new ActivityNotFoundException("Activity not found with id : " + id); } return activities.get(id); } @Override public <S extends Activity> S save(S s) { lastActivityId ++; activities.put(lastActivityId, s); return s; } //... }
FakeRepository를 작성한다면 실제 구현체를 조합하여 Repository 메서드를 오버라이딩 하도록 한다. FakeRepository를 실제 데이터 베이스에 접근하지 않고 메모리에 데이터를 관리하는 방식으로 Mock 객체의 단점을 보완할 수 있다.
FakeRepository 사용
class ActivityServiceTests { private ActivityRepository activityRepository = new FakeActivityRepository(); private ActivityService activityService = new ActivityService(activityRepository); //... }
FakeRepository는 위와 같이 생성자를 이용하여 다형성을 이용한 Fake구현체를 넣어 테스트 하고자 하는 대상에게 주입하여 테스트를 진행하도록 한다.
Fake의 단점
Fake는 과연 만능일까? Fake 구현체를 이용하여 Mock의 단점을 보완할 수 있었지만 위의 코드만 봐도 Fake구현체를 작성하는 것 자체가 상당히 많은 작업을 요하는 것 을 알 수 있다. 또한 연관관계의 데이터들을 모두 주입하기 위해서 Fake객체를 추가해야 할 경우 작성해야 하는 구현이 많아지고 Fake 구현체가 제대로 작동하는지 테스트할 별도의 FakeTest까지 작성해주어야 한다.
( 참고한 사이트 ❤️🔥 )
'Spring' 카테고리의 다른 글
인수테스트 (Acceptance Test) ① 환경 구축 및 작성 (0) 2022.02.08 테스트를 위한 Mock과 그 외의 Test Double (0) 2022.02.03 Service Layer의 단위테스트 작성 : (1) Mockito ② (0) 2022.02.03 Service Layer의 단위테스트 작성 : (1) Mockito ① (0) 2022.01.28 예외처리전략 ( ExceptionHandler ) 2 (0) 2022.01.13