실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기

Ch04. 요구사항 추가(책 통계, QueryDSL) - 책 통계 테스트 코드와 리펙토링

webmaster 2022. 11. 7. 21:08
728x90

테스트 코드

책 대여 권수를 확인하는 테스트

@Test
@DisplayName("책 대여 권수를 정상 확인한다")
fun countLoanedBookTest() {
    //given
    val saveUser = userRepository.save(User("김준호", null))
    userLoanHistoryRepository.saveAll(
        listOf(
            UserLoanHistory.fixture(saveUser, "A"),
            UserLoanHistory.fixture(saveUser, "B", UserLoanStatus.RETURNED),
            UserLoanHistory.fixture(saveUser, "C", UserLoanStatus.RETURNED),
        )
    )

    //when
    val result = bookService.countLoanedBook()

    //then
    assertThat(result).isEqualTo(1)
}
  • RETURNED 상태인 "B", "C" / LOANED 상태인 "A"를 저장한다.
  • 현재 대여중인 상태의 북 리스트의 size(1)를 반환하는지 확인한다

분야별 책 권수를 확인한다

@Test
@DisplayName("분야별 책 권수를 정상 확인한다.")
fun getBookStatisticsTest() {
    //given
    bookRepository.saveAll(
        listOf(
            Book.fixture("A", BookType.COMPUTER),
            Book.fixture("B", BookType.COMPUTER),
            Book.fixture("C", BookType.SCIENCE),
        )
    )

    //when
    val results = bookService.getBookStatistics()

    //then
    assertThat(results).hasSize(2)
    assertCount(results, BookType.COMPUTER, 2)
    assertCount(results, BookType.SCIENCE, 1)
    /*
    val computerDto = results.first { result -> result.type == BookType.COMPUTER }
    assertThat(computerDto.count).isEqualTo(2)

    val scienceDto = results.first { result -> result.type == BookType.SCIENCE }
    assertThat(scienceDto.count).isEqualTo(1)
     */
}

private fun assertCount(results: List<BookStatResponse>, type: BookType, count: Int) {
    assertThat(results.first { result -> result.type == type }.count).isEqualTo(count)
}
  • COMPUTER 타입을 책 2권 SCIENCE 타입을 책 1권을 저장한 뒤, 그룹별로 잘 조회되는지 확인한다.
  • 테스트 코드 또한 관리 대상으로 리펙토링하는 것이 중요하다.
    • 타입을 count를 검증해주는 함수를 만들어준다.

리펙토링

Service

@Transactional(readOnly = true)
fun getBookStatistics(): List<BookStatResponse> {

    return bookRepository.findAll()//List<Book>
        .groupBy { it -> it.type } //Map<BookType, List<Book>>
        .map { (type, books) -> BookStatResponse(type, books.size) } //List<BookStatResponse>
}

BookStatResponseDto

data class BookStatResponse(
    val type: BookType,
    val count: Int,
) {
   
}
  • 이전 코드는 함수형 프로그래밍에 적절하지 않다(var 키워드를 사용해야 하고, List 또한 변경 가능한 list가 돼야 하기 때문이다)
  • groupBy를 사용해 Map<book.type, List<Book>> 만든다.
  • map 함수를 통해 BookStatResponse 를 만드는데 type은 그대로고, count에 List<Book>을 넣어준다.
  • count를 val로 변경할 수 있고, 더이상 mutableList를 만들지 않아도 되고, 엘비스 연산자와 ?연산자를 남발하지 않아도 된다.

 

728x90