728x90
반응형
1. Junit5에서 사용되는 5가지 어노테이션
1) @Test : 테스트 메소드를 지정한다. 테스트 메소드를 싱행하는 과정에서 오류가 없으면 성공
2) @BeforeEach : 각 테스트 메소드가 수행되기 전에 실행되는 메소드를 지정. 매번 실행
3) @AfterEach : 각 테스트 메소드가 수행된 후에 실행되는 메소드를 지정. 매번 실행
4) @BeforeAll : 모든 테스트를 수행하기 전에 최초 1회 수행되는 메소드를 지정
5) @AfterAll : 모든 테스트를 수행한 후 최후 1회 수행되는 메소드를 지정
* BeforeAll과 AfterAll은 @JvmStatic을 붙여줘야한다.
package com.group.libraryapp
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class JunitTest {
companion object {
@BeforeAll
@JvmStatic
fun beforeAll() {
println("모든 테스트 시작 전")
}
@AfterAll
@JvmStatic
fun afterAll() {
println("모든 테스트 종료 후")
}
}
@BeforeEach
fun beforeEach() {
println("각 테스트 시작 전")
}
@AfterEach
fun afterEach() {
println("각 테스트 종료 후")
}
@Test
fun test1() {
println("테스트 1")
}
@Test
fun test2() {
println("테스트 2")
}
}
실행 결과
2. 단언문
- assertThat(확인하고 싶은 값)
- .isEqualTo(기대하는 값)
- .isTrue / .isFalse 주어진 값이 true인지 false인지 검증
- .hasSize(기대하는 사이즈)
- .extracting(name).containsExactlyInAnyOrder("A","B") : 해당하는 리스트들의 name만 가져와서 그 값이 정확히 A인지 B인지 검증. 순서는 검증하지 않기 때문에 순서는 중요하지 않음
- .containsExactly("A", "B") : 순서까지 검증
- assertThrows<IllegalArgumentException> {
function1()
} : function1 함수를 실행했을 때 IllegalArgumentException이 나오는지 검증 - val message = assertThrows<IllegalArgumentException> {
function1()
}.message
assertThat(message).isEqualTo("잘못된 값이 들어왔습니다") : message를 가져와 예외 메시지를 확인할 수 있음
3. Spring Boot 각 계층을 테스트 하는 방법
- Domain 계층 : 클래스를 테스트 하는 것과 동일
- Service, Repository 계층 : 스프링 빈을 사용하는 테스트 방법 사용 (@SpringBootTest), 데이터 위주의 검증
- Controller 계층 : 스프링 빈을 사용하는 테스트 방법 사용 (@SpringBootTest), 응답 받은 JSON을 비롯한 HTTP 위주의 검증
딱 1개의 계층만 테스트 한다면 보통은 Service 계층을 테스트
A를 보냈을 때 B가 잘 나오는지, 원하는 로직을 잘 수행하는지 검증 가능
4. 테스트 코드 작성
package com.group.libraryapp.service.user
import com.group.libraryapp.domain.user.User
import com.group.libraryapp.domain.user.UserRepository
import com.group.libraryapp.dto.user.request.UserCreateRequest
import com.group.libraryapp.dto.user.request.UserUpdateRequest
import org.assertj.core.api.AssertionsForInterfaceTypes.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
// @Autowired constructor를 붙이면 각각 @Autowired를 붙이지 않아도 됨
class UserServiceTest @Autowired constructor(
private val userRepository: UserRepository,
private val userService: UserService,
) {
// DB를 공유자원으로 사용하고 있기 때문에 각 테스트 코드를 실행한 뒤에 자원을 비우도록 하기 위함
@AfterEach
fun clean() {
userRepository.deleteAll()
}
@Test
@DisplayName("유저 저장이 정상 동작한다.")
fun saveUserTest() {
// given
val request = UserCreateRequest("아무개", null)
// when
userService.saveUser(request)
// then
val results = userRepository.findAll()
assertThat(results).hasSize(1)
assertThat(results[0].name).isEqualTo("아무개")
assertThat(results[0].age).isNull() // Java와 Kotlin의 자료형 차이 때문에 Exception 발생하는데 User에서 어노테이션을 붙여줘야함
}
@Test
@DisplayName("유저 조회가 정상 동작한다.")
fun getUsersTest() {
// given
userRepository.saveAll(listOf(
User("A", 20),
User("B", null)
))
// when
val results = userService.getUsers()
// then
assertThat(results).hasSize(2)
assertThat(results).extracting("name").containsExactlyInAnyOrder("A", "B")
assertThat(results).extracting("age").containsExactlyInAnyOrder(20, null)
}
@Test
@DisplayName("유저 업데이트가 정상 동작한다.")
fun updateUserNameTest() {
// given
val savedUser = userRepository.save(User("A", null))
val request = UserUpdateRequest(savedUser.id, "B")
// when
userService.updateUserName(request)
// then
val result = userRepository.findAll()[0]
assertThat(result.name).isEqualTo("B")
}
@Test
@DisplayName("유저 삭제가 정상 동작한다.")
fun deleteUserTest() {
// given
userRepository.save(User("A", null))
// when
userService.deleteUser("A")
// then
assertThat(userRepository.findAll()).isEmpty()
}
}
번외)
전체 테스트 코드를 실행하려면
인텔리제이에서 터미널에 ./gradlew test 명령어로 실행을 시키거나
우측에 있는 gradle 클릭 후 Tasks > verification > test 실행을 시키면 테스트 코드 전체를 실행시킬 수 있다.
728x90
반응형
'TIL > Kotlin' 카테고리의 다른 글
[TIL/Kotlin] Kotlin과 JPA를 사용할 때 이야기거리 3가지 (0) | 2023.12.23 |
---|---|
[TIL/Kotlin] Kotlin, SpringBoot, JPA nativeQuery 사용시 주의사항 (0) | 2023.12.05 |
[TIL/Kotlin] 우체국 Open API로 EMS 배송 추적하기 (0) | 2023.10.15 |
[TIL/Kotlin] 코틀린 고급문법_sealed 클래스, 위임된 프로퍼티, 클래스 위임 (0) | 2023.05.27 |
[TIL/Kotlin] 코틀린 고급문법_열거 클래스(Enum Class)와 열거 클래스에 프로퍼티와 멤버 함수 선언 및 활용하기 (0) | 2023.05.27 |