
최근 학습한 TDD를 실제로 적용하기 위해, 프로덕션 코드 작성 이전에 테스트 코드 먼저 작성해 보았다.
책에서 권장한 대로, 먼저 테스트 할 목록을 정리하였고
그 이후 예외적인 상황(이미 존재하는 email) 먼저 테스트를 진행하였다.
Given("사용자는 회원가입을 할 때") {
val dto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "구범모")
val blankNameDto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "")
val blankEmailDto = SignUpUserRequestDto("", "구범모")
val alreadyExistsEmailDto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "구범모")
When("빈칸이 아닌 이름을 입력하면") {
Then("회원가입에 성공하여 Response Dto를 반환한다") {
}
}
When("빈칸이 아닌 이메일을 입력하면") {
}
When("이미 존재하는 이메일이면") {
Then("예외가 발생한다") {
val exception = shouldThrow<RuntimeException> {
signUpUserService.signUp(alreadyExistsEmailDto)
}
}
}
When("빈칸인 이름을 입력하면") {
Then("예외가 발생한다") {
}
}
When("빈칸인 이메일을 입력하면") {
Then("예외가 발생한다")
}
}
Kotest의 BehaviorSpec 은 기본적으로 위와 같이 Given / When / Then을 호출한다.
나는 하나의 상황(Given) 아래에서 여러 입력 케이스에 대한 단위테스트를 진행하고 싶다.
하지만 그러려면 Given block 내에서, 여러개의 When절에서 필요한 dto, stubbing을 진행해 주어야 한다.
그렇게 되면 각 When절에서 필요하지 않은 필드가 공유되는 상황이 생긴다.
Given("사용자는") {
And("회원가입을 할 때") {
val dto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "구범모")
When("빈칸이 아닌 이름을 입력하면") {
Then("회원가입에 성공하여 Response Dto를 반환한다") {
}
}
}
And("회원가입을 할 때") {
val dto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "구범모")
When("빈칸이 아닌 이메일을 입력하면") {
Then("회원가입에 성공하여 Response Dto를 반환한다") {
}
}
}
And("회원가입을 할 때") {
val alreadyExistsEmailDto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "구범모")
every { signUpUserPort.existsByEmail(any()) } returns true
When("이미 존재하는 이메일이면") {
Then("예외가 발생한다") {
shouldThrow<RuntimeException> {
signUpUserService.signUp(alreadyExistsEmailDto)
}
}
}
}
And("회원가입을 할 때") {
val blankNameDto = SignUpUserRequestDto("rnqjaah1234@gmail.com", "")
When("빈칸인 이름을 입력하면") {
Then("예외가 발생한다") {
}
}
}
And("회원가입을 할 때") {
val blankEmailDto = SignUpUserRequestDto("", "구범모")
When("빈칸인 이메일을 입력하면") {
Then("예외가 발생한다") {
}
}
}
}
Kotest 공식문서를 참고하여, 위와 같이 Given과 When절 사이에 And절을 추가하여,
And절 block 내부에서 각 테스트에 사용할 필드(dto)와 stubbing을 진행하여 각 테스트간 필드 / stubbing을 격리하였다.