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)
    }
}

참고 글