This manual is a work in progress and is currently incomplete.

9 Testing Ratpack applications

Ratpack provides testing support, both at the functional and unit level. The ratpack-test library contains the core support, and ratpack-test-groovy provides convenient Groovy extensions.

Note: The ratpack and ratpack-groovy Gradle plugins auto configure these libraries to be added to the test classpath.

9.1 Unit testing

The primary integration point between Ratpack and your code is the Handler contract. Ratpack provides the UnitTest.invoke() and GroovyUnitTest.invoke() for contriving the invocation of a handler. As the routing of requests is also implemented via handlers in Ratpack, this can also be used to test the routing.

Ratpack doesn’t couple to any particular test framework. It only provides some utilities that you can use from whatever test framework you choose. However, we strongly recommend using the Groovy based Spock Framework, even if your application is implemented in Java.

There is no special setup or teardown required for unit testing Ratpack applications, as by definition they require no server infrastructure.

9.2 Functional testing

Functional testing for Ratpack is built up around the ApplicationUnderTest.

This interface provides the address of the running application. Implementations of this interface will take care of starting the server for you.

9.2.1 TestHttpClient

Ratpack provides TestHttpClient in ratpack-test-groovy, this is a client that makes it very simple to test status codes and responses.

Note below we use @Delegate so we just need to call get() in the when block instead of client.get().


import ratpack.groovy.test.LocalScriptApplicationUnderTest import ratpack.groovy.test.TestHttpClient import ratpack.groovy.test.TestHttpClients import ratpack.test.ApplicationUnderTest class SiteSmokeSpec { LocalScriptApplicationUnderTest aut = new LocalScriptApplicationUnderTest() @Delegate TestHttpClient client = TestHttpClients.testHttpClient(aut) def "Check Site Index"() { get("index.html") assert response.statusCode == 200 assert response.body.asString().contains('<title>Ratpack: A toolkit for JVM web applications</title>') } def "Check Site Root"() { get() assert response.statusCode == 200 assert response.body.asString().contains('<title>Ratpack: A toolkit for JVM web applications</title>') } def cleanup() { aut.stop() } }

9.2.2 Geb

Geb can also be used we just need to set up the correct base URL and make sure the test app is shut down.

To set the correct base URL we will use the ServerBackedApplicationUnderTest instance to get the address and give that to the Geb browser instance.

For shutting down the app we will call stop in the cleanup function.

An example of a Geb based test is available here. ```

9.2.3 Application subsets, modules and extensions

The ratpack.test.embed package (provided by the ratpack-test library) provides the EmbeddedApplication interface and implementations. These can be used to functionally test features in isolation, by creating small Ratpack apps within test cases and is actually the basis for how Ratpack itself is tested. This approach is most commonly used for functionally testing reusable Ratpack components (e.g. Guice modules) but can also be used for functionally testing a subset of an application.

The LaunchConfigEmbeddedApplication is a convenient abstract super class, where implementors only need to provide a LaunchConfig to define the application to test. The ratpack.groovy.test.embed package (provided by the ratpack-groovy-test library) provides the ClosureBackedEmbeddedApplication implementation that uses user supplied closures as the basis of the application to test. This is the preferred implementation to use as it provides Guice support, flexibility and is easy to use.

The EmbeddedApplication type extends the ApplicationUnderTest type. This makes them convenient to use with the TestHttpClient mechanism provided by the ratpack-groovy-test library.