Grails quick tip: Testing Spock Interactions wrapped by the Executor plugin

We ran into an interesting issue today working with Spock, Grails and the executor plugin.

The executor plugin allows you to move tasks that might be long running into the background of your application.

In this post, I will show you how to unit test spock interactions wrapped inside the runAsync methods provided by the plugin.

A typical block of code within executor would look like this:


myServiceMethod() {
... non Async code ...
runAsync{
someOtherService.asyncMethod( var1 )
}
}

We ran into a peculiar problem while moving our code into the executor plugin today.

We normally mock interactions in spock within our unit tests to make sure that certain methods are called.

our tests run something like this:


when:
service.serviceMethod()
then:
1 * someOtherService.asyncMethod( _ )

This works fine when you have no code within the runAsync block, but if you move code into the runAsync closure, the method call don’t get detected by Spock anymore.

It meant that moving our code to make it asynchronous also broke our unit specs. All our interactions would seem to disappear as they were now being ran in another thread.

The way we were able to solve this problem is to just rewrite the runAsync method in the service metaclass within our tests, so we added:


given:
service.metaClass.runAsync = { it() }
when:
service.serviceMethod()
then:
1 * someOtherService.asyncMethod( _ )

The first line basically says ‘take the code within the runAsync closure, and just execute it’.

After adding this, all our unit specs pass again.

One thought on “Grails quick tip: Testing Spock Interactions wrapped by the Executor plugin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s