SW 개발
Spring Boot, JUnit, AssertJ를 이용한 REST API 유닛 테스트 구현하기
지단로보트
2022. 10. 27. 23:52
개요
- 이번 글에서는 Spring Boot 기본 프로젝트에
AssertJ
만을 추가하여 프로젝트에 구현된 REST API에 대한 유닛 테스트를 작성하는 방법을 간단히 정리하였다.
build.gradle.kts
- 프로젝트 루트의 build.gradle.kts에 아래 라이브러리를 추가한다.
dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.assertj:assertj-core:3.23.1")
}
@SpringBootTest 클래스 작성
- 유닛 테스트의 본체가 되는 클래스를 작성할 차례이다. 실제 컨트롤러에 대응되는 유닛 테스트는 개별 클래스로 작성하고 본체 클래스에서 정의한 순서대로 호출하는 방식이다.
import org.junit.jupiter.api.*
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.test.web.server.LocalServerPort
@SpringBootTest(
classes = [DemoApplication::class],
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@TestMethodOrder(OrderAnnotation::class)
class FooApplicationTests {
@LocalServerPort
private val port = 0
@Autowired
private lateinit var restTemplate: TestRestTemplate
@Test
@Order(1)
fun fooTest() {
FooControllerTests.test1(restTemplate, port)
FooControllerTests.test2(restTemplate, port)
}
@Test
@Order(2)
fun barTest() {
BarControllerTests.test3(restTemplate, port)
BarControllerTests.test4(restTemplate, port)
}
}
- 클래스 레벨에
@TestMethodOrder(OrderAnnotation::class)
을 명시하여@Order({number})
의 number 숫자가 적은 메써드가 우선순위로 실행되도록 작성했다. 또하, 실제 각 컨트롤러에 대한 유닛 테스트를 대응하는 개별 테스트 클래스로 분리한 후 본체 클래스에서 호출하는 형태로 작성하여 가독성을 향상시켰다.
개별 컨트롤러 테스트 클래스 작성
- 본체에서 호출할 개별 컨트롤러 테스트 클래스를 아래와 같이 작성한다.
import org.assertj.core.api.Assertions.assertThat
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.http.HttpStatus
object FooControllerTests {
fun test1(restTemplate: TestRestTemplate, port: Int) {
val result = restTemplate.getForEntity(
"http://localhost:$port/v1/foo/1",
String::class.java
)
assertThat(result.statusCode).isEqualTo(HttpStatus.OK)
}
fun test2(restTemplate: TestRestTemplate, port: Int) {
val result = restTemplate.getForEntity(
"http://localhost:$port/v1/foo/2",
String::class.java
)
assertThat(result.statusCode).isEqualTo(HttpStatus.OK)
}
}
참고 글
- Testing the Web Layer
- Testing POST APIs using Spring Boot TestRestTemplate
- The Guide to RestTemplate
- Exploring the Spring Boot TestRestTemplate
- Testing with Spring Boot and @SpringBootTest
- Using Conditions with AssertJ Assertions
- Spring boot tests, multiple test classes run in particular order (class order, not the method order)
- Adding Integration Tests in Spring Boot with Testcontainers
- Spring Boot: MySQL Container Integration