Programming/TDD Project

Pull Request 010 - 자유게시글 조회 기능 TDD로 구현해보기

JKROH 2023. 11. 10. 15:20
반응형

 이번에는 게시글 조회 기능이다. 앞서 작성과 수정 기능을 마치고 삭제 기능을 먼저 조회하려 했으나, 수정 기능에서부터 겹쳤던 조회 기능을 모른척 할 수가 없었다.

 

 조회 기능의 로직은 다음과 같다.

 

  1. FreeBoardService#getFreeBoard(long id) 를 통해 조회 명령을 받는다.
  2. FreeBoardQueryService#readEntityById(long id) 메서드를 통해 레포지토리에 FreeBoard 엔티티 조회 쿼리를 날린다.
  3. 조회한 엔티티 쿼리를 Response DTO로 바꿔 반환한다.

 우선 2번에 대한 테스트를 진행해볼 것이다. 먼저 테스트를 진행할 클래스를 생성하고 필요한 필드들을 채우고, 테스트 메서드를 만들었다.

class FreeBoardQueryServiceTest {

    @Mock
    private FreeBoardRepository freeBoardRepository;

    @InjectMocks
    private FreeBoardQueryService freeBoardQueryService;

    @Test
    void testReadEntityById() {

    }
}

 

 FreeBoardQueryService#readEntityById()의 핵심은 id 값으로 적절한 값이 들어오면 엔티티를 반환하지만, 부적절한 값이 들어오면 예외를 던져야한다는 것이다. 따라서 우리는 두 가지를 테스트해야 한다.

  • 적절한 id가 인자로 넘어가면 엔티티를 반환한다.
  • 부적절한 id가 인자로 넘어가면 예외를 던진다.

 이제 테스트 메서드를 채워보자. 먼저 적절한 id값과 부적절한 id값 그리고 적절한 id값을 제공했을 때 반환받을 객체가 필요할 것이다.

    @Test
    void testReadEntityById() {
        // given
        long appropriateId = 1L;
        long inappropriateId = 0L;

        Optional<FreeBoard> testEntity = Optional.of(FreeBoard.builder()
                .title("title")
                .content("content")
                .build());
    }

 

 이제 MockRespoisotry에서 반환할 값을 처리해주자.

    @Test
    void testReadEntityById() {
        // given
        long appropriateId = 1L;
        long inappropriateId = 0L;

        Optional<FreeBoard> testEntity = Optional.of(FreeBoard.builder()
                .title("title")
                .content("content")
                .build());

        //when
        given(freeBoardRepository.findById(appropriateId)).willReturn(testEntity);
        given(freeBoardRepository.findById(inappropriateId)).willReturn(Optional.empty());

        FreeBoard foundEntity = freeBoardQueryService.readEntityById(appropriateId);
    }

 

 이제 마지막 단계다. 다시 한 번 테스트 해볼 두 가지를 가지고 상태값을 상정하자.

  • 적절한 id값으로 찾아온 foundEntity와 Optional객체인 testEntity에서 뽑아온 객체는 같아야한다.
  • 부적절한 id값으로 FreeBoardQueryService#readEntityByID()를 실행하면 예외를 던진다.
    • 이번에는 테스트 작성을 위해 RuntimeException으로 예외를 설정했지만, 추후 예외 클래스를 제작할 예정이다.
    @Test
    void testReadEntityById() {
        // given
        long appropriateId = 1L;
        long inappropriateId = 0L;

        Optional<FreeBoard> testEntity = Optional.of(FreeBoard.builder()
                .title("title")
                .content("content")
                .build());

        //when
        given(freeBoardRepository.findById(appropriateId)).willReturn(testEntity);
        given(freeBoardRepository.findById(inappropriateId)).willReturn(Optional.empty());

        FreeBoard foundEntity = freeBoardQueryService.readEntityById(appropriateId);

        //then
        assertThat(foundEntity).isEqualTo(testEntity.get());
        assertThrows(RuntimeException.class, ()->freeBoardQueryService.readEntityById(inappropriateId));
    }

 

 then절의 실행 값들을 통해 테스트를 마무리 할 수 있을 것이다. 이를 기반으로 readEntityById()를 구현하자.

@Service
public class FreeBoardQueryService {
    private final FreeBoardRepository freeBoardRepository;

    public FreeBoardQueryService(FreeBoardRepository freeBoardRepository) {
        this.freeBoardRepository = freeBoardRepository;
    }

    @Transactional(readOnly = true)
    public FreeBoard readEntityById(long id) {
        return freeBoardRepository.findById(id).orElseThrow(() -> 
                new RuntimeException());
    }
}

 

 테스트가 잘 수행됨을 확인할 수 있다. 앞선 단계에서 테스트 메서드를 작성해보았기 때문에 테스트 메서드를 처음부터 한 단계씩 작성하는 과정을 모두 적지는 않았다.

 

전체 코드는 링크에서 확인할 수 있다.

반응형