docs
docs copied to clipboard
[Kotlin] @BeforeAll and @AfterAll throws exceptions when used in kotlin
Describe the bug @BeforeAll and @AfterAll throws exceptions when used in kotlin
To Reproduce
class MyStepDefinitions {
companion object {
@JvmStatic
@BeforeAll
fun beforeAll() {
println("before all")
}
@JvmStatic
@AfterAll
fun afterAll() {
println("after all")
}
}
//some steps declaration
Throws exception:
Before All/After All failed
io.cucumber.core.exception.CompositeCucumberException: There were 2 exceptions. The details are in the stacktrace below.
at io.cucumber.core.runtime.RethrowingThrowableCollector.getThrowable(RethrowingThrowableCollector.java:57)
at io.cucumber.core.runtime.CucumberExecutionContext.getThrowable(CucumberExecutionContext.java:81)
at io.cucumber.core.runtime.CucumberExecutionContext.finishTestRun(CucumberExecutionContext.java:76)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:85)
at io.cucumber.core.cli.Main.run(Main.java:87)
at io.cucumber.core.cli.Main.main(Main.java:30)
Suppressed: io.cucumber.java.InvalidMethodSignatureException: A method annotated with BeforeAll or AfterAll must have one of these signatures:
* public static void before_or_after_all()
at void com.lohika.cucumber.MyStepDefinitionsMethod$Companion.beforeAll()
at io.cucumber.java.InvalidMethodSignatureException$InvalidMethodSignatureExceptionBuilder.build(InvalidMethodSignatureException.java:52)
at io.cucumber.java.JavaStaticHookDefinition.createInvalidSignatureException(JavaStaticHookDefinition.java:44)
at io.cucumber.java.JavaStaticHookDefinition.requireValidMethod(JavaStaticHookDefinition.java:28)
at io.cucumber.java.JavaStaticHookDefinition.<init>(JavaStaticHookDefinition.java:17)
at io.cucumber.java.GlueAdaptor.addDefinition(GlueAdaptor.java:30)
at io.cucumber.java.JavaBackend.lambda$loadGlue$1(JavaBackend.java:42)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:67)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:58)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:33)
at io.cucumber.java.JavaBackend.lambda$loadGlue$2(JavaBackend.java:40)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at io.cucumber.java.JavaBackend.loadGlue(JavaBackend.java:40)
at io.cucumber.core.runner.Runner.<init>(Runner.java:56)
at io.cucumber.core.runtime.SingletonRunnerSupplier.createRunner(SingletonRunnerSupplier.java:44)
at io.cucumber.core.runtime.SingletonRunnerSupplier.get(SingletonRunnerSupplier.java:35)
at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:35)
at io.cucumber.core.runtime.CucumberExecutionContext.getRunner(CucumberExecutionContext.java:114)
at io.cucumber.core.runtime.CucumberExecutionContext.runBeforeAllHooks(CucumberExecutionContext.java:65)
at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:81)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
... 2 more
Suppressed: io.cucumber.java.InvalidMethodSignatureException: A method annotated with BeforeAll or AfterAll must have one of these signatures:
* public static void before_or_after_all()
at void com.lohika.cucumber.MyStepDefinitionsMethod$Companion.beforeAll()
at io.cucumber.java.InvalidMethodSignatureException$InvalidMethodSignatureExceptionBuilder.build(InvalidMethodSignatureException.java:52)
at io.cucumber.java.JavaStaticHookDefinition.createInvalidSignatureException(JavaStaticHookDefinition.java:44)
at io.cucumber.java.JavaStaticHookDefinition.requireValidMethod(JavaStaticHookDefinition.java:28)
at io.cucumber.java.JavaStaticHookDefinition.<init>(JavaStaticHookDefinition.java:17)
at io.cucumber.java.GlueAdaptor.addDefinition(GlueAdaptor.java:30)
at io.cucumber.java.JavaBackend.lambda$loadGlue$1(JavaBackend.java:42)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:67)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:58)
at io.cucumber.java.MethodScanner.scan(MethodScanner.java:33)
at io.cucumber.java.JavaBackend.lambda$loadGlue$2(JavaBackend.java:40)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at io.cucumber.java.JavaBackend.loadGlue(JavaBackend.java:40)
at io.cucumber.core.runner.Runner.<init>(Runner.java:56)
at io.cucumber.core.runtime.SingletonRunnerSupplier.createRunner(SingletonRunnerSupplier.java:44)
at io.cucumber.core.runtime.SingletonRunnerSupplier.get(SingletonRunnerSupplier.java:35)
at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:35)
at io.cucumber.core.runtime.CucumberExecutionContext.getRunner(CucumberExecutionContext.java:114)
at io.cucumber.core.runtime.CucumberExecutionContext.runAfterAllHooks(CucumberExecutionContext.java:70)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:84)
... 2 more
Your Environment
- Versions used 7.1.0
You have to use package level functions. For example:
package io.cucumber.example
import io.cucumber.java.AfterAll
import io.cucumber.java.BeforeAll
@BeforeAll
fun beforeAll() {
println("before all")
}
@AfterAll
fun afterAll() {
println("after all")
}
When using a companion object, Kotlin will create an class MyStepDefinitionsMethod$Companion
which has non-static methods. The @JvmStatic
annotation does not prevent this, it only adds the static methods to MyStepDefinitionsMethod
.As a result Cucumber will detect both the static method ons MyStepDefinitions
as well as the non-static methods on MyStepDefinitions$Companion
and complain about the second one.
@mpkorstanje thanks a lot, could you be added to docs?
They're kept here, feel free to send a pull request.
https://github.com/cucumber/docs
@mpkorstanje & @mlvandijk I can add this info to the doc. Which section of the doc would you like to add it to? May I propose to add it to https://cucumber.io/docs/guides/10-minute-tutorial/ as a note? Please let me know what you think and assign this issue to me :)
https://docs.cucumber.io/docs/cucumber/api/
Under "Hooks".
@mpkorstanje, Thanks for your suggestion and assigning it to me! I am thinking of place it under the tip of which heading reads Think twice before you use Before (see screenshot below), but it will be shown as warning not as tip. Please let me know what you think.
Also, I have noticed that there is a Hugo partial layout named warn.html
, but that uses message is-danger
css classes instead of message is-warning
. Can I change warn.html to use message is-warning
and create a new Hugo partial payout for danger, naming danger.html
and using message is-danger
css classes?
I wouldn't know how to answer that one. I'm not that deep into the docs project. Might be best to stick with what there is for this PR and sort out the danger/warn difference on a separate issue.
Also, I have noticed that there is a Hugo partial layout named
warn.html
, but that usesmessage is-danger
css classes instead ofmessage is-warning
. Can I change warn.html to usemessage is-warning
and create a new Hugo partial payout for danger, namingdanger.html
and usingmessage is-danger
css classes?
I would say, let's do it. Just: do we use that partial in the doc? That would help to check if we break something or not.
Also, I have noticed that there is a Hugo partial layout named
warn.html
, but that usesmessage is-danger
css classes instead ofmessage is-warning
. Can I change warn.html to usemessage is-warning
and create a new Hugo partial payout for danger, namingdanger.html
and usingmessage is-danger
css classes?I would say, let's do it. Just: do we use that partial in the doc? That would help to check if we break something or not.
@aurelien-reeves ,
Yes, we use the partial named warn.html
in step-definitions.md
at line #193. You can see it live at https://cucumber.io/docs/cucumber/step-definitions/ but you'll have click javascript
tab.
Thanks for your suggestion I will fix this but creating a separate issue for easy reference
Looks like the original issue has been fixed. Can this issue be closed?