一個現代化、雲原生的框架一定要考慮到測試,有足夠的測試才能讓應用在改版與升版時更有保證。Quarkus 整合了 JUnit5 讓我們可以很容易的寫出測試的程式碼
先來看一眼測試 REST endpoint,這裡是整合了 Rest Assured 與 Kotlin 的 DSL。 可以用 Gherkin 的風格來撰寫測試,也接近 user story 的表達。
今天的程式已經放置在 GitHub
    @Test
    fun `test list all`() {
        Given {
            contentType(ContentType.JSON)
        } When {
            get("/films")
        } Then {
            statusCode(200)
            body("title", `is`(listOf("A New Hope", "Return"...)))
        }
    }
這樣的表達方式會比 Java 版本的 Rest Assured 語意更清楚
測試的程式碼都會在專案的 src/test/kotlin,前幾天的 sample project 都有自帶一個 test 的 stub code : GreetingResourceTest.kt。可以看到要在 test class 打上 @QuarkusTest 及 Method 打上 @Test
@QuarkusTest
class GreetingResourceTest {
    @Test
    fun testHelloEndpoint() {
        given()
          .`when`().get("/hello")
          .then()
             .statusCode(200)
             .body(`is`("Hello from RESTEasy Reactive"))
    }
}
所以我們可以 copy 這個 class, rename成我們要的 filmResoruceTest.kt 。這裡我有另外用 test startup event 先塞了三份資料,所以get list all 時預期會抓出三個name
    @Test
    fun `test list all`() {
        Given {
            // 一定要加,不然會噴 415 
            contentType(ContentType.JSON)
        } When {
            // http get 的位置
            get("/films")
        } Then {
            // Assertion 200 return
            statusCode(200)
            // 回來的 json array 有三個,裡頭的 title 各是...
            body("title", `is`(listOf("A New Hope", "The Empire Strikes Back", "Return Of The Jedi")))
        }
    }
打上 @TestMethodOrder 可以讓測試照指定的順序執行
@QuarkusTest
@TestMethodOrder(value = MethodOrderer.OrderAnnotation::class)
例如我們要先新增,然後修改最後刪除就可以這樣寫
   @Test
    @Order(1)
    fun `test add`() {
       ....
    }
    @Test
    @Order(2)
    fun `test update after add`() {
       ....
    }
    @Test
    @Order(3)
    fun `test delete`() {
      ....
    }
新增一個 maven run : test 就可以執行測試

由 console 可以看到 quarkus 幫我們起了一個 mongodb, 並且將設定指過去。這個這測試的ap 會起在 8081。

剛剛都只講到從 REST endpoint 進去測,其實我們也可以直接 Inject Quarkus 所管理的 bean 來測。因為要測的大部份是 suspend function, 這裡要用 runBlocking 包起來才能編譯
@QuarkusTest
class FilmRepositoryTest {
    @Inject
    lateinit var filmRepository: FilmRepository
    @Test
    fun `test count`() {
        runBlocking {
            filmRepository.count().awaitSuspending()
                .let { assertEquals(3, it) }
        }
    }
}