spock-mockable icon indicating copy to clipboard operation
spock-mockable copied to clipboard

Compilation error when mocking Groovy class

Open rosincc opened this issue 2 years ago • 4 comments

import spock.lang.Specification

class T extends Specification {
    def t() {
        given:
        def a = Spy(A)
    }
}

class A {}

The execution reports the following error:

Groovyc: While compiling [tests of spock-mockable-static]: BUG! exception in phase 'canonicalization' in source unit '/Users/xxx/workspace/spock-mockable-static/src/test/groovy/T.groovy' ClassNode#getTypeClass for A called before the type class is set
	at org.codehaus.groovy.ast.ClassNode.getTypeClass(ClassNode.java:1465)
	at org.codehaus.groovy.ast.ClassNode.getTypeClass(ClassNode.java:1459)
	at java.util.Optional.map(Optional.java:215)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.extractClass(MockVisitor.java:88)
	at java.util.Optional.flatMap(Optional.java:241)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.visitClassExpression(MockVisitor.java:59)
	at org.codehaus.groovy.ast.expr.ClassExpression.visit(ClassExpression.java:36)
	at org.codehaus.groovy.ast.GroovyCodeVisitor.lambda$visitListOfExpressions$0(GroovyCodeVisitor.java:209)
	at java.util.ArrayList.forEach(ArrayList.java:1259)
	at org.codehaus.groovy.ast.GroovyCodeVisitor.visitListOfExpressions(GroovyCodeVisitor.java:209)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitTupleExpression(CodeVisitorSupport.java:249)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitArgumentlistExpression(CodeVisitorSupport.java:367)
	at org.codehaus.groovy.ast.expr.ArgumentListExpression.visit(ArgumentListExpression.java:75)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.visitMethodCallExpression(MockVisitor.java:51)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor.visit(MockVisitor.java:37)
	at io.github.joke.spockmockable.ast.visitors.SpecificationVisitor$Visitor.visitMethodCallExpression(SpecificationVisitor.java:37)
	at org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:77)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitBinaryExpression(CodeVisitorSupport.java:202)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitDeclarationExpression(CodeVisitorSupport.java:335)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitDeclarationExpression(ClassCodeVisitorSupport.java:154)
	at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:117)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:204)
	at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:41)
	at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:86)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:168)
	at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:70)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:142)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:115)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:110)
	at org.codehaus.groovy.ast.ClassNode.visitMethods(ClassNode.java:1131)
	at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1124)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:52)
	at io.github.joke.spockmockable.ast.visitors.SpecificationVisitor.visit(SpecificationVisitor.java:24)
	at io.github.joke.spockmockable.ast.SpecificationProcessor.process(SpecificationProcessor.java:14)
	at io.github.joke.spockmockable.ast.SourceUnitProcessor.lambda$process$1(SourceUnitProcessor.java:22)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1235)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
	at io.github.joke.spockmockable.ast.SourceUnitProcessor.process(SourceUnitProcessor.java:22)
	at io.github.joke.spockmockable.ast.Processor.analyze(Processor.java:21)
	at io.github.joke.spockmockable.ast.MockableASTTransformation.visit(MockableASTTransformation.java:34)
	at org.codehaus.groovy.transform.ASTTransformationVisitor.lambda$addPhaseOperationsForGlobalTransforms$5(ASTTransformationVisitor.java:377)
	at org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:896)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:692)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:666)
	at org.jetbrains.groovy.compiler.rt.GroovyCompilerWrapper.compile(GroovyCompilerWrapper.java:48)
	at org.jetbrains.groovy.compiler.rt.DependentGroovycRunner.runGroovyc(DependentGroovycRunner.java:120)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.jetbrains.groovy.compiler.rt.GroovycRunner.intMain2(GroovycRunner.java:80)
	at org.jetbrains.groovy.compiler.rt.GroovycRunner.intMain(GroovycRunner.java:40)
	at org.jetbrains.groovy.compiler.rt.GroovycRunner.main(GroovycRunner.java:19)

rosincc avatar Apr 10 '23 09:04 rosincc

Hi @hellsof

could you provide a more detailed example? I can reproduce the error but I'm entirely sure about what you are actually trying to do in the first place. If I create a groovy class in the compile scope (main) everything works fine.

Are you really trying to spy a class with is placed alongside your test classes?

joke avatar Apr 10 '23 10:04 joke

There is no specific application scenario for the time being. When writing a demo program, this exception is reported, but no relevant records are found, and this problem is accidentally discovered when it is about to give up.

rosincc avatar Apr 10 '23 12:04 rosincc

@hellsof It has something to do with the compile time groovy transformation for this extension. I'll take a closer look today.

Regards Joke

joke avatar Apr 11 '23 06:04 joke

Coming across this issue as well when using thrown with my custom Exception class in Groovy. Here's a short test case example:

    class FooException extends RuntimeException {}

    def exceptionThrower() { throw new FooException() }

    def "Test"() {
        when:
            exceptionThrower()
        then:
            thrown(FooException)
    }

This fails compilation (error below). If you swap thrown(FooException) by thrown(RuntimeException) compilation and test pass.

Caused by: BUG! exception in phase 'canonicalization' in source unit 'xxxxx/Test.groovy' ClassNode#getTypeClass for xxxxx.Test$FooException called before the type class is set
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.extractClass(MockVisitor.java:88)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.visitClassExpression(MockVisitor.java:59)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor$Visitor.visitMethodCallExpression(MockVisitor.java:51)
	at io.github.joke.spockmockable.ast.visitors.MockVisitor.visit(MockVisitor.java:37)
	at io.github.joke.spockmockable.ast.visitors.SpecificationVisitor$Visitor.visitMethodCallExpression(SpecificationVisitor.java:37)
	at io.github.joke.spockmockable.ast.visitors.SpecificationVisitor.visit(SpecificationVisitor.java:24)
	at io.github.joke.spockmockable.ast.SpecificationProcessor.process(SpecificationProcessor.java:14)
	at io.github.joke.spockmockable.ast.SourceUnitProcessor.lambda$process$1(SourceUnitProcessor.java:22)
	at io.github.joke.spockmockable.ast.SourceUnitProcessor.process(SourceUnitProcessor.java:22)
	at io.github.joke.spockmockable.ast.Processor.analyze(Processor.java:21)
	at io.github.joke.spockmockable.ast.MockableASTTransformation.visit(MockableASTTransformation.java:34)
	at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:271)
	at org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:64)
	at org.gradle.api.internal.tasks.compile.GroovyCompilerFactory$DaemonSideCompiler.execute(GroovyCompilerFactory.java:97)
	at org.gradle.api.internal.tasks.compile.GroovyCompilerFactory$DaemonSideCompiler.execute(GroovyCompilerFactory.java:76)
	at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkAction.execute(AbstractDaemonCompiler.java:135)
	at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
	at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:49)
	at org.gradle.workers.internal.AbstractClassLoaderWorker$1.create(AbstractClassLoaderWorker.java:43)
	at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
	at org.gradle.workers.internal.AbstractClassLoaderWorker.executeInClassLoader(AbstractClassLoaderWorker.java:43)
	at org.gradle.workers.internal.IsolatedClassloaderWorker.run(IsolatedClassloaderWorker.java:49)
	at org.gradle.workers.internal.IsolatedClassloaderWorker.run(IsolatedClassloaderWorker.java:30)
	at org.gradle.workers.internal.WorkerDaemonServer.run(WorkerDaemonServer.java:87)
	at org.gradle.workers.internal.WorkerDaemonServer.run(WorkerDaemonServer.java:56)
	at org.gradle.process.internal.worker.request.WorkerAction$1.call(WorkerAction.java:138)
	at org.gradle.process.internal.worker.child.WorkerLogEventListener.withWorkerLoggingProtocol(WorkerLogEventListener.java:41)
	at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:135)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:49)

ClaudioConsolmagno avatar Jul 21 '23 10:07 ClaudioConsolmagno