Marcin Erdmann

Groovy, Grails, Geb...

Verifying that Groovy Remote Control endpoint is exposed in your application

I'm a big fun of grey box functional testing of web applications. I understand grey box testing as setting up your test (for example bootstraping data in db that the test requires) programmatically instead of via the UI. Sometimes you will also want to do parts of your verification in this way.

Some people use fixture endpoints for that but I'm not a fan of this solution for two reasons: the fixture code lives along your production code and fixture endpoints are a nightmare to maintain - what people end up doing is to have one endpoint with a lot of setup for all the tests which bootstraps a lot of data that is not essential to every single test... Oh, and there is one more reason - you want your test setup to live as close to your test as possible.

There is a better solution to this problem available for JVM apps - Groovy Remote. It provides an endpoint that allows you to send groovy closures to the remote application that get executed in the JVM of that application. It ships with a servlet class and also a class that starts up a simple http server with the endpoint so you can use it in a variety of scenarios - for both container and standalone apps. There is a Grails plugin available and I also created a Gaelyk compatible version.

Quite often when using Groovy Remote you want to be able to manually verify that the endpoint is exposed under a certain url and that it isn't exposed when deployed to production. I will show how it can be done using curl when using Grails Remote Control.

To get a Groovy Remote endpoint in your Grails app all you need to do is install the plugin via BuildConfig.groovy:

plugins {
    compile ":remote-control:1.4"
}

Assuming that we called our Grails app remote-control-test the remote control url will be http://localhost:8080/grails-remote-test/grails-remote-control. Let's start the application in dev mode, grails run-app, and verify that the endpoint is not exposed via a simple curl POST:

'curl -i --data "" -s http://localhost:8080/grails-remote/grails-remote-control | head -n 1'

We should get the following as the result:

HTTP/1.1 404 Not Found

When running the app in prod environment (grails prod run-app) we should get the exact same result. On the other hand if we are expecting the endpoint to be exposed like for example when running in test environment (grails test run-app) we can use a slightly different curl command:

'curl -i --data "" -s http://localhost:8080/grails-remote-test/grails-remote-control | egrep "(HTTP/1.1 415 Unsupported Media Type|Only remote control commands can be sent)" -o'

The expected result is:

HTTP/1.1 415 Unsupported Media Type

Only remote control commands can be sent

Only remote control commands can be sent

By default the Remote Control endpoint is only exposed in test environment. You can enable it for other environments by adding the following to your Config.groovy:

environments {
    qa {
        remoteControl.enabled = true
    }
}

Then run your app using grails -Dgrails.env=qa run-app and verify that the endpoint is exposed using the previously mentioned curl commands.