在Grails测试中使用Groovy Trait失败

时间:2014-12-02 21:48:52

标签: grails groovy spock

如何在Grails Spock测试中实现Groovy的新特性?每次尝试时,我都会得到一个看起来像这样的堆栈跟踪。是否有一些我可能不知道的Groovy路径的限制?

JDK版本:

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版本:

Grails version: 2.4.3

简化代码:

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
}

}

堆栈跟踪:

 [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)

2 个答案:

答案 0 :(得分:8)

我们的项目中出现了同样的异常,这种异常大量使用了特征:

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

我的同事发现,只要特征超过10个字段,就会发生这种情况。我们不知道这种行为的起源。

作为一种解决方法,我们使用特征继承:

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

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

值得注意的是,我们在Android上使用Groovy,因此调整ColimMc提议的JVM选项不是一种选择。

答案 1 :(得分:-1)

在我看来,使用特征的脚本字段存在限制。如果使用特征的实现中的字段数达到一定大小(我的情况是34个方法),则抛出此异常。我目前遇到了同样的问题,我正试图解决它。

我可以使用以下方式绕过Groovy:

-Djava.util.Arrays.useLegacyMergeSort=true

如此处所述:https://stackoverflow.com/a/13575810/1673785

我认为它与他们的GETTER_FIRST_COMPARATOR比较器有关,它不会返回0.它只返回1和-1,我认为这是它提到合同违规的原因。