which spock plugin to use with Grails 2.0?

95 views
Skip to first unread message

Roshan Dawrani

unread,
Dec 19, 2011, 5:06:14 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
Hi,

I am looking into Grails 1.3.7 to 2.0 upgrade and some Spock tests are failing to compile with errors like below:

---------------------------------------------------------------------------------------------------------------------------------------------------
ClientSpec.groovy: 8: The return type of java.lang.Object mockDomain(java.lang.Class) in foo.Spec is incompatible with void mockDomain(java.lang.Class) in grails.plugin.spock.UnitSpec
. At [-1:-1]
 @ line 8, column 1.
   class ClientSpec extends UnitSpec
---------------------------------------------------------------------------------------------------------------------------------------------------

I am currently using org.spockframework:spock:0.6-groovy-1.8-SNAPSHOT plugin, which pulls in spock-grails-support-0.6-groovy-1.8-SNAPSHOT.jar

Is this the correct version of plugin to use with Grails 2.0? Any hints on why I am getting the above mentioned error?

--
Roshan

Luke Daley

unread,
Dec 19, 2011, 5:11:02 AM12/19/11
to spockfr...@googlegroups.com

You should be using “0.6-SNAPSHOT” as the version of the plugin.

Roshan Dawrani

unread,
Dec 19, 2011, 5:25:39 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
Even with 0.6-SNAPSHOT, I am getting the following error. I don't know if it is related, but spock-0.6-SNAPSHOT plugin still seems to be pulling in the snapshot jar - spock-grails-support-0.6-groovy-1.8-SNAPSHOT.jar

Which framework adds mockDomain(Class) to the class under test - Grails or Spock? Wondering where does the inconsistency lie.

---------------------------------------------------------------------------------
The return type of java.lang.Object mockDomain(java.lang.Class) in ClientSpec is incompatible with void mockDomain(java.lang.Class) in grails.plugin.spock.UnitSpec
. At [-1:-1]
 @ line 8, column 1.
   class ClientSpec extends UnitSpec
---------------------------------------------------------------------------------



--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To post to this group, send email to spockfr...@googlegroups.com.
To unsubscribe from this group, send email to spockframewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/spockframework?hl=en.




--
Roshan

Roshan Dawrani

unread,
Dec 19, 2011, 6:11:33 AM12/19/11
to us...@grails.codehaus.org, spockfr...@googlegroups.com
On Mon, Dec 19, 2011 at 4:25 PM, l...@ldaley.com <l...@ldaley.com> wrote:
Is the new Grails 2 test mixing a must?
No, can you share all of ClientSpec.groovy ?

I cut down ClientSpec.groovy to as shown below, and still ran into the same error:

---------------------------------------------------
package foo

import grails.plugin.spock.UnitSpec

class ClientSpec extends UnitSpec
{
    def constraints()
    {
    }
}
--------------------------------------------------- 

--
Roshan

Roshan Dawrani

unread,
Dec 19, 2011, 6:13:56 AM12/19/11
to us...@grails.codehaus.org, spockfr...@googlegroups.com
On Mon, Dec 19, 2011 at 4:31 PM, Sam Carr <sam...@mac.com> wrote:
Note that your Spock tests should subclass Specification, not UnitSpec with Grails 2. Then you should use the @TestFor and @Mock annotations to hook into Grails' new test support. So a controller unit test might start as below. See the Grails 2.0 testing docs for more information.

Hi Sam, I haven't switched to using Grails new test support, but I just checked with Luke and it is not a must. So I assume, even using the previous 1.3.7 style test support is supported, but I am running into an issue with that.

-- 
Roshan

Luke Daley

unread,
Dec 19, 2011, 6:15:25 AM12/19/11
to spockfr...@googlegroups.com
It seems like you have a version of ClientSpec floating around that has been compiled with something else.

Long shot, but try a full clean build (i.e. grails clean & rm -rf ~/.grails/2.0.0/projects/«project»)

Roshan Dawrani

unread,
Dec 19, 2011, 6:36:00 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 4:45 PM, Luke Daley <lda...@gmail.com> wrote:
It seems like you have a version of ClientSpec floating around that has been compiled with something else.

Long shot, but try a full clean build (i.e. grails clean & rm -rf ~/.grails/2.0.0/projects/«project»)

Nope. That's not it. I have been cleaning from both the places in every cycle, when I have tried it. I just cleaned them anyway, and still ran into the error.

Is it Grails that normally adds mockDomain(Class), mockDomain(Class, List) to classes under test? I would have liked looking at that transform, etc to see if it is adding a method with return type not void, but Object.

--
Roshan

Luke Daley

unread,
Dec 19, 2011, 6:50:43 AM12/19/11
to spockfr...@googlegroups.com
There shouldn't be any transforms kicking in. I can't think of what would be unique about your project, because this definitely works for others.

See if you can reproduce in a small isolated project and share it, if I can poke at it it might make the process quicker.

Roshan Dawrani

unread,
Dec 19, 2011, 7:33:02 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 5:20 PM, Luke Daley <lda...@gmail.com> wrote:
Is it Grails that normally adds mockDomain(Class), mockDomain(Class, List) to classes under test? I would have liked looking at that transform, etc to see if it is adding a method with return type not void, but Object.

There shouldn't be any transforms kicking in. I can't think of what would be unique about your project, because this definitely works for others.

See if you can reproduce in a small isolated project and share it, if I can poke at it it might make the process quicker.

Hi Luke, 

I poked around a bit. The mockDomain() methods are added to ClientSpec by GrailsASTUtils.addDelegateInstanceMethods(...) - via TestMixinTransformation.weaveMixinsIntoClass()

Regarding Groovy's verifier rejecting the ClientSpec with "The return type of java.lang.Object mockDomain(java.lang.Class) in foo.Spec is incompatible with void mockDomain(java.lang.Class) in grails.plugin.spock.UnitSpec" -> 

      -  the reason is that we also use Groovy++ in our Grails application and there is an additional Verifier visit Groovy++ performs for its own thing. That early Verifier visit is resulting in this issue. So, it's an issue with Grails 2.0 / Groovy 1.8.4 + Groovy++ marriage. That's why you don't commonly see this issue elsewhere. Not a Grails issue, but something between Groovy++ and Groovy 1.8.4. Will ask around more there.

-- 
Roshan

Roshan Dawrani

unread,
Dec 19, 2011, 7:47:32 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 6:03 PM, Roshan Dawrani <roshan...@gmail.com> wrote:
Not a Grails issue, but something between Groovy++ and Groovy 1.8.4. Will ask around more there.

Made a mistake at the very end. It is an issue between Grails 2.0 and Spock's grails plugin.

The problem originates from the fact that DomainClassUnitTestMixin defines "mockDomain" as
--------------------------------------------------------------------------------------------
def mockDomain(Class domainClassToMock, List domains = [])
--------------------------------------------------------------------------------------------

whereas grails.plugin.spock.UnitSpec defines "mockDomain" as:
--------------------------------------------------------------------------------------------
void mockDomain(Class, List)
--------------------------------------------------------------------------------------------

Because of this inconsistency, Groovy Verifier rejects the compilation as ClientSpec with that error that return types are incompatible.

So, is it is a bug on Grails 2.0 or Spock's grails plugin? Where should I file?

--
Roshan

Luke Daley

unread,
Dec 19, 2011, 7:55:02 AM12/19/11
to spockfr...@googlegroups.com
Is DomainClassUnitTestMixin being applied implicitly?

Roshan Dawrani

unread,
Dec 19, 2011, 8:04:11 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 6:25 PM, Luke Daley <lda...@gmail.com> wrote:

Is DomainClassUnitTestMixin being applied implicitly?

I have not started using Grails 2.0 new test support (no usage of @TestFor in my app yet, but TestForTransformation is still kicking in and weaving in these mixin classes, like DomainClassUnitTestMixin). 

If that's what you mean, then yes, it is being applied implicitly.

--
Roshan

Roshan Dawrani

unread,
Dec 19, 2011, 8:12:53 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
I wonder is that's what org.codehaus.groovy.grails.test.compiler.GrailsTestCompiler.makeCompileUnit() is doing - effectively adding @TestFor to all the test classes and forcing an implicit visit by TestForTransformation on all of them.

Regardless of how TestForTransformation is coming into the picture, the consistency between the following two is still a bug between Grails 2.0 and Spock's Grails plugin:

DomainClassUnitTestMixin:
--------------------------------------------------------------------------------------------
def mockDomain(Class domainClassToMock, List domains = [])
--------------------------------------------------------------------------------------------

grails.plugin.spock.UnitSpec:
--------------------------------------------------------------------------------------------
void mockDomain(Class, List)
--------------------------------------------------------------------------------------------

Roshan Dawrani

unread,
Dec 19, 2011, 8:50:59 AM12/19/11
to spockfr...@googlegroups.com, Grails Users

Luke Daley

unread,
Dec 19, 2011, 9:49:42 AM12/19/11
to spockfr...@googlegroups.com
I have local tests that I would expect to hit this if it were being added automatically to every class. I doubt that it would be as that's very dangerous.

Could there be something else in your environment that is triggering this?

Roshan Dawrani

unread,
Dec 19, 2011, 10:25:06 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 8:19 PM, Luke Daley <lda...@gmail.com> wrote:
I have local tests that I would expect to hit this if it were being added automatically to every class. I doubt that it would be as that's very dangerous.

Could there be something else in your environment that is triggering this?

As far as I see at this point, it's not related specifically to my environment now. I wish I could see what your local tests cover - to compare and see why they are not hitting this issue. Just to cross-check once more - you have local Spock tests that do not extend UnitSpec, but do not use @TestFor?

Anyway, the link I see in Grails 2.0 is:

   1) _GrailsTest.groovy.compileTests() chooses to use extended compiler 'testc' (GrailsTestCompiler) for unit tests classes.

   2) GrailsTestCompiler injects a ASTTransformationCustomizer for TestFor

   3) Because of the ASTTransformationCustomizer added in 2), Groovy now introduces TestForTransformation for all unit test classes, which in turn weaves in methods from DomainClassUnitTestMixin into the unit test classes.

In this chain, what do you see that can be local to a particular environment? I can look more, if you can provide a hint.

--
Roshan

Luke Daley

unread,
Dec 19, 2011, 10:33:57 AM12/19/11
to spockfr...@googlegroups.com

On 19/12/2011, at 3:25 PM, Roshan Dawrani wrote:

> On Mon, Dec 19, 2011 at 8:19 PM, Luke Daley <lda...@gmail.com> wrote:
> I have local tests that I would expect to hit this if it were being added automatically to every class. I doubt that it would be as that's very dangerous.
>
> Could there be something else in your environment that is triggering this?
>
> As far as I see at this point, it's not related specifically to my environment now. I wish I could see what your local tests cover - to compare and see why they are not hitting this issue. Just to cross-check once more - you have local Spock tests that do not extend UnitSpec, but do not use @TestFor?

It's here: https://github.com/spockframework/spock-grails

>
> Anyway, the link I see in Grails 2.0 is:
>
> 1) _GrailsTest.groovy.compileTests() chooses to use extended compiler 'testc' (GrailsTestCompiler) for unit tests classes.
>
> 2) GrailsTestCompiler injects a ASTTransformationCustomizer for TestFor
>
> 3) Because of the ASTTransformationCustomizer added in 2), Groovy now introduces TestForTransformation for all unit test classes, which in turn weaves in methods from DomainClassUnitTestMixin into the unit test classes.
>
> In this chain, what do you see that can be local to a particular environment? I can look more, if you can provide a hint.

Didn't you say you had Groovy++ in the mix?

Roshan Dawrani

unread,
Dec 19, 2011, 10:38:40 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 9:03 PM, Luke Daley <lda...@gmail.com> wrote:

It's here: https://github.com/spockframework/spock-grails

Thanks. Will look at the tests there.
 
Didn't you say you had Groovy++ in the mix?

Yes, using Groovy++ is what is different about our project, but after saying that I have been providing all the evidence in Grails / Spock-Grails plugin code that is the root cause of the error. The two methods originating from Grails and Spock-Grails plugin that differ only in return type have nothing to do with Groovy++. It's an inconsistency where it is pointed to, is it not?

--
Roshan

Roshan Dawrani

unread,
Dec 19, 2011, 11:33:35 AM12/19/11
to spockfr...@googlegroups.com, Grails Users
On Mon, Dec 19, 2011 at 9:03 PM, Luke Daley <lda...@gmail.com> wrote:

It's here: https://github.com/spockframework/spock-grails

>
> Anyway, the link I see in Grails 2.0 is:
>
>    1) _GrailsTest.groovy.compileTests() chooses to use extended compiler 'testc' (GrailsTestCompiler) for unit tests classes.
>
>    2) GrailsTestCompiler injects a ASTTransformationCustomizer for TestFor
>
>    3) Because of the ASTTransformationCustomizer added in 2), Groovy now introduces TestForTransformation for all unit test classes, which in turn weaves in methods from DomainClassUnitTestMixin into the unit test classes.
>
> In this chain, what do you see that can be local to a particular environment? I can look more, if you can provide a hint.

Looked at your tests for spock-grails plugin. 

The difference is that you use gradle based build for it. So (refer 1-3 above), _GrailsTest.groovy does not come into the picture as it does when "grails test-app unit:" is done. That's why GrailsTestCompiler and then weaving of DomainClassUnitTestMixin also does not come into the picture for your tests. So, it's all clean.

I am attaching an almost blank grails application created with Grails 2.0.0.

All I did was:

a) create an app
b) add a dependency to plugin ':spock:0.6-SNAPSHOT'
c) grails create-domain-class book
d) grails test-app unit: -> this now fails to compile BookSpec added in 3) due to the very same error that I have been reporting and explaining :-)

Cheers.

--
Roshan
grails2-spock-unittest-issue.zip

Roshan Dawrani

unread,
Dec 21, 2011, 2:34:35 PM12/21/11
to Grails Users, spockfr...@googlegroups.com
On Tue, Dec 20, 2011 at 10:36 PM, l...@ldaley.com <l...@ldaley.com> wrote:
Fixed.

Thanks. Will verify soon with our app.
 
I can't see anything, I'm stumped.

I found why. Details below :-)
 
> That's why GrailsTestCompiler and then weaving of DomainClassUnitTestMixin also does not come into the picture for your tests. So, it's all clean.

That's not the case, the Gradle build is delegating to the Grails build system so they are compiled the same way. I'm at a a loss to explain why these tests pass.

Went nearly crazy debugging through Grails 2.0 + Gradle + Groovy 1.8.4 + grails-gradle-plugin + grails-launcher + spock-grails plugins, and here is the simple difference between my application and your spock-grails with tests:

   - In my app, for a unit test like AndroidClientSpec, I have a domain class AndroidClient. In your app, for unit tests like UnitSpecSpec, GoodSpec, there are no corresponding classes UnitSpec or Good

   - The way Grails 2.0 TestForTransformation works is that it auto-magically applies @TestFor and weaves all its mock / mixin stuff to a unit test only if for FooTests or FooSpec unit test, it finds a Foo artefact.

So, if you want to cover this auto-magic mixing of old style unit tests (that extend UnitSpec) in your spock-grails test application, then you need to introduce a correspnding artefact (domain class, say), and you should see that then Grails 2.0 will then weave stuff into that test, while skipping other tests that don't have a matching class to test / mock for.

Cheers.

--
Roshan
Reply all
Reply to author
Forward
0 new messages