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

(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.)
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
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With