Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Junit assertions don't work when called inside a Javalin handler

I have this test that launches a service at port 7000 and inside the only endpoint I do a failing assertion:

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

The problem is that the test always passes (but it should fail):

enter image description here

(same behavior happens by running ./gradlew test)

... even though there's a console output claiming that a test failed:

[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)
    ..

Probably, it's being run in another thread, but I wonder if there's a way to attach it to the same context. (Weirdly, in another scenario in my app - that I couldn't isolate - it properly fails.)

like image 269
Luís Soares Avatar asked Nov 17 '25 11:11

Luís Soares


1 Answers

TLDR

To make the test fail as you'd expect, add an assertion on the response you get from your Javalin instance.

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

Details

There're two distinct steps in the test: new Javalin instance configuration + build, and calling that instance with a HttpClient.

In Javalin configuration + build step it gets instructed to do assertTrue(false) when called on the / endpoint. assertTrue(false) will throw an AssertionFailedError, but the behavior will be the same if you throw something else there. Now, as many (all?) other webservers, Javalin / Jetty will try to catch any uncaught exceptions that happen within it and return a HTTP response with code 500 (Internal Server Error).

Indeed, this all happens in another thread, as internally a Jetty webserver instance is being launched, which does the port listening, HTTP request / response handling and other important stuff.

So when later in the test an HTTP call is performed to the new Javalin instance, it gets the 500 (Internal Server Error) response successfully, and as originally there are no assertions on the response and there were no uncaught exceptions, the test is deemed successful.

like image 162
2 revs, 2 users 55%Cameron McCloud Avatar answered Nov 19 '25 00:11

2 revs, 2 users 55%Cameron McCloud



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!