我有此测试在端口7000处启动服务,并且在唯一的端点内执行失败的断言:

@Test
fun `javalin assertion should fail`() {
    Javalin.create()
            .get("/") { assertTrue(false) }
            .start()

    newHttpClient().send(
            HttpRequest.newBuilder()
                    .uri(URI.create("http://localhost:7000/"))
                    .GET().build(),
            discarding()
    )
}

问题是测试总是通过的(但应该失败):

kotlin - 在Javalin处理程序中调用Junit断言不起作用-LMLPHP

(通过运行./gradlew test也会发生相同的行为)

...即使有控制台输出声称测试失败:
[Test worker] INFO io.javalin.Javalin - Listening on http://localhost:7000/
[Test worker] INFO io.javalin.Javalin - Javalin started in 356ms \o/
[qtp2100106358-22] ERROR io.javalin.Javalin - Exception occurred while servicing http-request
org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
    at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
    ..

可能是在另一个线程中运行,但是我想知道是否有一种方法可以将其附加到相同的上下文中。
(很奇怪,在我的应用程序的另一种情况下-我无法隔离-它正确地失败了。)

最佳答案

TLDR

要使测试失败,请在从Javalin实例获得的响应上添加一个断言。

    @Test
    fun `javalin assertion should fail`() {
        Javalin.create()
            .get("/") { assertTrue(false) } // or any expression that throws an Exception, like Kotlin's TODO()
            .start()

        val javalinResponse: HttpResponse<Void> = newHttpClient().send(
            HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:7000/"))
                .GET().build(),
            discarding()
        )

        assertThat(javalinResponse.statusCode()).isEqualTo(200) // will fail with Expected: 200, Actual: 500
    }

细节

测试中有两个不同的步骤:新的Javalin实例配置+构建,以及使用HttpClient调用该实例。

在Javalin配置+构建步骤中,当它在assertTrue(false)端点上调用时,它被指示执行/assertTrue(false)将抛出一个AssertionFailedError,但是如果在其中抛出其他内容,其行为将相同。现在,与许多其他Web服务器一样,Javalin / Jetty将尝试捕获其中发生的任何未捕获的异常,并返回带有代码500(内部服务器错误)的HTTP响应。

确实,这一切都是在另一个线程中发生的,因为内部启动了一个Jetty Web服务器实例,该实例负责端口侦听,HTTP请求/响应处理以及其他重要内容。

因此,当稍后在测试中对新的Javalin实例执行HTTP调用时,它将成功获得500(内部服务器错误)响应,并且由于最初没有响应声明,也没有未捕获的异常,因此该测试被视为成功。

10-04 13:40