TIL

2023.11.30 TIL -  테스트의 범위..

내배캠 심화 개인 과제로 전에 했던 to-do-list 앱에 대한 계층별 단위 테스트 코드를 작성하고있다.

 

코드 작성 중 할 일 완료 처리 기능 에 대해 단위 테스트 코드를 작성하려니 해당 메소드 타입이 void 여서 

어떻게 테스트를 작성해야할지 고민을 했다.

 

고민한 문제


public void completeToDo(Long toDoId, MemberDto memberDto) {
    ToDo toDo = toDoRepository.findById(toDoId)  // 완료처리할 할 일 Find
            .orElseThrow(ToDoNotFoundException::new);

	//권한 검증
    checkMember(toDo.getMember().getId(), memberDto.id(), ACCESS_DENIED_MESSAGE);

	//이미 완료처리 되어있으면 throw
    if (toDo.isDone()) {
        throw new AlreadyCompleteToDoException();
    }

    toDo.complete(true); //더티체킹
}

 

해당 코드의 흐름은 

1. 해당 할 일을 찾고,

2. 수정 권한있는지를 체크하고,

3. 이미 완료처리된 할 일인지 확인한 후

4. 완료처리를 하는 코드이다.

 

해당 코드에서 완료처리에 대해 테스트를 하려면 toDo 인스턴스의 isDone 값을 확인해야한다고 생각해서 짜려고했는데,

해당 toDo를 가져올 수가 없었다.

 

그래서 튜터님께 물어보기로 한다..

 

 

방법


우선 튜터님은 짜려고하는 범위가 다르다고 하셨다.

서비스레이어 테스트라고 서비스 메소드를 테스트하는 것이아니라 해당 메서드내에서 '서비스가 영향을 끼치는지' 가 중요하다고 하셨다.

 

위에 코드에서 

 

 ToDo toDo = toDoRepository.findById(toDoId)  // 완료처리할 할 일 Find
            .orElseThrow(ToDoNotFoundException::new);

코드와

    toDo.complete(true); //더티체킹

이 코드는 영속성 컨텍스트영역, 즉 Repository 범위에 속하므로 해당 범위에서 테스트를 하는게 맞는 것 같다고 하셨다.

 

결국 서비스 레이어에서 테스트를 해야하는 건 

	//권한 검증
    checkMember(toDo.getMember().getId(), memberDto.id(), ACCESS_DENIED_MESSAGE);

	//이미 완료처리 되어있으면 throw
    if (toDo.isDone()) {
        throw new AlreadyCompleteToDoException();
    }

이 검증 로직이 되는 것이다.

 

그래서 테스트 코드는 저 검증로직에 의해 예외가 발생하지 않으면 성공하게 끔 테스트 코드를 작성했다.

@DisplayName("할 일 완료 요청 시 할 일 완료 처리") //TODO: 물어보기
@Test
void givenToDoId_whenCompleteToDo_thenUpdateComplete () throws Exception {
   //Given
   Member toDoWriter = getMember(1L);
   MemberDto memberDto =MemberDto.from(toDoWriter);

   Long toDoId = 1L;
   ToDo toDo = createToDo(toDoId, toDoWriter);

   given(toDoRepository.findById(toDoId)).willReturn(Optional.of(toDo));

   //When & Then
   assertThatCode(()-> sut.completeToDo(toDoId, memberDto)).doesNotThrowAnyException();
}

 

* 예외가 안날 경우 성공인 테스트케이스를 작성할 때, asserThatThrownBy 는 사용할 수가 없다.

 assertTahtThorwnBy는 무조건 예외가 발생할 때 사용할 수 있는 메소드이다. 이럴 때는 위와 같이 assertThatCode를 사용하자.

 

결론

내가 이해한 결론은 다음과 같다.

서비스레이어 범위에 속하는 로직을 테스트하고 그외 로직은 해당 범위에 맞는 영역에서 테스트를 하자.

 

* 추가적인 방법으로 메소드의 리턴 타입을 수정하거나, 저위의 검증로직을 메소드로 뺴서 해당 메소드로 테스트하거나 인데,
  이 방법들도 위에 결론을 벗어나지 않는다.

 

 

 

 

 

 

728x90