Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Groovy Trait in Grails Test Fails

How can I implement Groovy's new traits in my Grails Spock tests? Every time I try, I get a stacktrace that looks like this. Is there some limitation of Groovy trails that I might not be aware of?

JDK Version:

java version "1.7.0_65"
OpenJDK Runtime Environment (IcedTea 2.5.3) (7u71-2.5.3-0ubuntu0.14.04.1)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)

Groovy Verison:

Groovy Version: 2.3.6 JVM: 1.7.0_65 Vendor: Oracle Corporation OS: Linux

Grails Version:

Grails version: 2.4.3

Simplified Code:

import grails.test.mixin.Mock
@Mock([AnalyticFilters])
trait ControllerTestBase {
public void setupCommonStuff(boolean setupIdCall = false) {
params.devId = TEST_DEV_ID
    // mocking version filter
    params.version = "v${TEST_VERSION}"

    defineBeans{
       CacheService(cacheServiceMock: "createMock")
    }

    CommonParams.parseParams(params)

    cacheMock = applicationContext.getBean("cacheServiceMock")

    if(setupStoreIdCall) {
        cacheMock.demandExplicit.makeCompositeKey(0..20) { List<String> list ->
            def (String uuid, String orgUuid) = list
            return "foobar"
        }
    }

}
}

@TestFor(AuditController)
public class AuditControllerSpecs extends Specification implements ControllerTestBase {

private def auditServiceFactory

public String testAuditData = "{audit:'whatever'}"

public void setup() {
    setupCommonParams()

    defineBeans {
        auditServiceFactory(GrailsMock, AuditService)
        auditService(auditServiceFactory: "createMock")
    }
    auditServiceFactory = applicationContext.getBean("auditServiceFactory")
    auditServiceFactory.demand.writeEventToMongo { BasicDBObject data -> }
    controller.auditService = applicationContext.getBean('auditService', AuditService)
}

def "calling productAudit should return with 200 and OK"() {

    given:
    request.JSON = JSON.parse(testAuditData)
    request.method = 'POST'
    when:
    withFilters(action: "productAudit") {
        controller.productAudit()
    }
    then:

    def res = JSON.parse(response.text)

    expect:
    response.status == 200
    res.message == "OK"
    100 == 2
}

}

Stacktrace:

 [groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  [groovyc] General error during canonicalization: Comparison method violates its general contract!
  [groovyc] 
  [groovyc] java.lang.IllegalArgumentException: Comparison method violates its general contract!
  [groovyc]     at java.util.TimSort.mergeLo(TimSort.java:747)
  [groovyc]     at java.util.TimSort.mergeAt(TimSort.java:483)
  [groovyc]     at java.util.TimSort.mergeCollapse(TimSort.java:410)
  [groovyc]     at java.util.TimSort.sort(TimSort.java:214)
  [groovyc]     at java.util.TimSort.sort(TimSort.java:173)
  [groovyc]     at java.util.Arrays.sort(Arrays.java:659)
  [groovyc]     at java.util.Collections.sort(Collections.java:217)
  [groovyc]     at org.codehaus.groovy.transform.trait.TraitComposer.applyTrait(TraitComposer.java:183)
  [groovyc]     at org.codehaus.groovy.transform.trait.TraitComposer.doExtendTraits(TraitComposer.java:105)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit$4.call(CompilationUnit.java:188)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1047)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:583)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:561)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:538)
  [groovyc]     at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:517)
  [groovyc]     at org.codehaus.groovy.tools.FileSystemCompiler.compile(FileSystemCompiler.java:59)
  [groovyc]     at org.codehaus.groovy.tools.FileSystemCompiler.doCompilation(FileSystemCompiler.java:215)
  [groovyc]     at org.codehaus.groovy.ant.Groovyc.runCompiler(Groovyc.java:1104)
  [groovyc]     at org.codehaus.groovy.ant.Groovyc.compile(Groovyc.java:1155)
  [groovyc]     at org.codehaus.groovy.grails.compiler.Grailsc.compile(Grailsc.java:78)
  [groovyc]     at org.codehaus.groovy.ant.Groovyc.execute(Groovyc.java:770)
  [groovyc]     at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
  [groovyc]     at sun.reflect.GeneratedMethodAccessor51.invoke(Unknown Source)
  [groovyc]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  [groovyc]     at java.lang.reflect.Method.invoke(Method.java:606)
  [groovyc]     at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
  [groovyc]     at groovy.util.AntBuilder.performTask(AntBuilder.java:319)
  [groovyc]     at groovy.util.AntBuilder.nodeCompleted(AntBuilder.java:264)
  [groovyc]     at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:147)
  [groovyc]     at groovy.util.AntBuilder.doInvokeMethod(AntBuilder.java:203)
  [groovyc]     at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
like image 220
HappyCoder86 Avatar asked Dec 02 '14 21:12

HappyCoder86


1 Answers

The same exception occurs in our project which makes heavy use of traits:

java.lang.IllegalArgumentException: Comparison method violates its general contract!

My colleague found out that this happens as soon as a trait has more than 10 fields. The origin of this behavior is unknown to us.

As a workaround we make use of trait inheritance:

trait Foo extends MoreFoo {
    //this has 10 fields
}

trait MoreFoo{
    //this has some more fields but not more than 10
}

It is noteworthy that we use Groovy on Android so adjusting JVM options as proposed by ColimMc is not an option.

like image 146
EightBitBoy Avatar answered Nov 08 '22 15:11

EightBitBoy