Grails 3.1.0 Unit Testing With RestBuilder

After the recent upgrade to Grails 3.1.0 we discovered that we were unable to run any unit tests that were previously testing services that used RestBuilder. Previously we were simply using metaClass behaviour to override the post, get, etc methods directly in the RestBuilder class. This changed and we had to invent a new way to keep these services under test.

The solution I came up with is below. A demo project is located at github.

Note: A fix has been added to Grails 3.1.1 that should address this particular problem.

BaseRestBuilderSpec

I created a base Specification called BaseRestBuilderSpec.groovy that we would extend from any unit test that was testing classes using RestBuilder.

MockRestBuilder

Then I created a MockRestBuilder.groovy class in the src/groovy (or src/test) folder.

Using the src/groovy is important for us due to the class being used across multiple projects and the core plugin src/test artifacts would not get pulled in. If your project is a simple layer without the use of inline plugins then src/test would probably work for you.

Here is the code for the MockRestBuilder. It is a bit long to embed.

Sample Specification

The unit test for a service looks like the following. To change the behavior of post, get, put, etc simply just metaClass the method on the MockRestBuilder object.

Here is what the service under test might look like. This is using an async task to complete the post which is why the test uses the Promise.get() to ensure the closure is invoked above.

One caveat is that you can not have your rest builder variable typed to RestBuilder unless you want to get a type cast exception. You can get around this by simply using the def keyword as in the example above.

Cheers!