3일차에 공부하다보니 다음과 같은 고민을 하게됐다.

JPA에서 @Transactional을 무조건 붙여야할까? Kotlin에서 JpaRepository를 쓸 때 Optional을 안쓰는 법이 있을까?

그리고 생각보다 시간을 많이 잡아먹었던 문제가 있었다.

WebMvc 테스트가 안됐던 이유

위 내용들에 대해 정리해보았다.

1. JPA에서 @Transactional을 무조건 붙여야할까?

습관적으로 서비스에서 @Transactional을 붙였었다. 하지만 레포지토리에 저장하는 등 하나만 실행을 한다면 과연 저 애너테이션이 필요할까? 결론적으로는 필요없다. 명시적으로 트랜잭션 경계를 구분해야할 필요성이 있을 때, 트랜잭션 격리수준, 예외 등을 설정할 때 등에 사용하면 된다.

2. Kotlin에서 JpaRepository를 쓸 때 Optional 안쓰는 법

    fun getFundingProposalByIdOrNull(id: Long): FundingProposal? =
        repository.findByIdOrNull(id) ?: throw EmptyResultDataAccessException(1)

이미 nullable을 리턴하는 메서드들이 다 있다!

3. WebMvc 테스트가 안됐던 이유

이전에 작성했던 kotest+mockk 코드가 작동하지 않았던 이유를 찾았다.

@WebMvcTest(ProposeController::class)
@AutoConfigureMockMvc
class ProposeUpdateTest(@Autowired val mockMvc: MockMvc) : FunSpec() {
    @MockkBean
    private lateinit var service: ProposeService

    init {
        beforeTest {
            service = mockk()
            every { service.createFundingProposal(any()) } returns FundingProposal(1L, "제안서 제목")
            every { service.updateFundingProposal(any(), any()) } returns FundingProposal(1L, "새로운 제안서 제목")
        ...
        }
}

이유는 mockk 라이브러리의 문제가 아니라 kotest에서 스프링 의존성을 주입하는 방법을 몰랐었기 때문이다.

  1. 클래스 바디의 init 블록 안에 Springextension을 넣어주거나
@WebMvcTest(ProposeController::class)
@AutoConfigureMockMvc
class ProposeUpdateTest2(@Autowired val mockMvc: MockMvc) : FunSpec() {
    override fun extensions() = listOf(SpringExtension) //이렇게

    @MockkBean
    private lateinit var service: ProposeService
	...
  1. 클래스 바디에 테스트 함수를 작성하지 말고 상속받는 Spec의 인자로 넣어준다.
@WebMvcTest(ProposeController::class)
@AutoConfigureMockMvc
class ProposeUpdateTest2(
    val mockMvc: MockMvc,
    @MockkBean private var service: ProposeService
) : FunSpec({
//테스트할 내용
...