cucumber / cucumber-jvm

Cucumber for the JVM
https://cucumber.io
MIT License
2.69k stars 2.02k forks source link

Aspectj annotation is being ignored while using Spring and Cucumber v7.10.0 onwords #2886

Closed Hakky54 closed 1 month ago

Hakky54 commented 1 month ago

👓 What did you see?

I am using Cucumber alongside with Spring ans Aspectj. This setup always worked. I was on version 7.2.3 of cucumber. I tried bumping it to 7.18.0 however some part of my tests failed. It was not picking up the aspectj annotations of the before and after step. I am not qure what is causing the issue. However If I downgrade to version 7.9.0 it still works. If I bump it to 7.10.0 it fails.

✅ What did you expect to see?

I would expect my existing test suite still be working

📦 Which tool/library version are you using?

JDK 17 Maven

🔬 How could we reproduce it?

  1. Git clone https://github.com/Hakky54/mutual-tls-ssl.git
  2. Adjust pom.xml in the root directory of the project. Change version of cucumber to 7.10.0
  3. run mvn clean verify it will throw nullpointer exception

The before and after call in LogExecutionTimeAspect.java is being ignored somehow while it is still working on version 7.9.0

📚 Any additional context?

No response

mpkorstanje commented 1 month ago

Interesting. Haven't quite got the time to dig into a bug project like this, but could you put @CucumberContextConfiguration on a separate class?

Hakky54 commented 1 month ago

I have tried that, but then I end up getting the well known error messsage:

io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.

For example:

   @CucumberContextConfiguration
   @SpringBootTest(classes = TestConfig.class)
   public class CucumberSpringConfiguration { }
Or: 

   @CucumberContextConfiguration
   @ContextConfiguration( ... )
   public class CucumberSpringConfiguration { }

    at io.cucumber.spring.SpringFactory.start(SpringFactory.java:100)
    at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:134)
    at io.cucumber.core.runner.Runner.runPickle(Runner.java:70)
    at io.cucumber.junit.PickleRunners$NoStepDescriptions.lambda$run$0(PickleRunners.java:151)
    at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:129)
    at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
    at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:129)
    at io.cucumber.junit.PickleRunners$NoStepDescriptions.run(PickleRunners.java:148)
    at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:144)
    at io.cucumber.junit.FeatureRunner.runChild(FeatureRunner.java:28)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at io.cucumber.junit.FeatureRunner.run(FeatureRunner.java:137)
    at io.cucumber.junit.Cucumber.runChild(Cucumber.java:196)
    at io.cucumber.junit.Cucumber.runChild(Cucumber.java:89)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at io.cucumber.junit.Cucumber$RunBeforeAllHooks.evaluate(Cucumber.java:266)
    at io.cucumber.junit.Cucumber$RunAfterAllHooks.evaluate(Cucumber.java:281)
    at io.cucumber.junit.Cucumber$StartTestRun.evaluate(Cucumber.java:233)
    at io.cucumber.junit.Cucumber$FinishTestRun.evaluate(Cucumber.java:248)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

      io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.

I was a bit hasty yesterday when creating the issue. I have added here a more detailed steps to reproduce it:

So if you are able to open this project in your IDEA, Eclipse or Visual Studio Code. Add a breakpoint here: LogExecutionTimeAspect.java Start the server by running the main method: App.java Start cucumber test in debug mode with the runner ClientRunnerIT.java and you will see it will stop at the breakpoint. Now if you update the version to 7.10.0 in pom.xml recompile the project with mvn clean compile and start the cucumber runner again it won't stop at the breakpoint in LogExecutionTimeAspect.java

I created this project to help others to understand ssl/tls. So it is a tutorial having spring boot as a server and the client module has over 40+ http clients as example to give others also code examples with actual working tests. And I use cucumber in the client module to test all of them. It contains a mixture of Java, Kotlin and Scala code which the project can build. It has worked so far, but I am not able to understand why bumping cucumber makes the AspectJ pointcut fail. So the workaround for me is to remove the following line in the feature file: Hello.feature#L9 and remove AspectJ and not logging execution time. So that won't be a big deal actually, but I am just curious what is causing in version 7.10.0 that it won't work anymore and maybe you know the answer 😄

I hope this detailed description is a bit more helpful compared to my initial issue description

mpkorstanje commented 1 month ago

That is informative!

Could you try annotating the SpringBootHelper with @CucumberContextConfiguration instead and make sure its package is on the glue path? Additionally your BaseStepDefs definitions should not extend the SpringBootHelper.

Hakky54 commented 1 month ago

Thank you! That worked like a charm. Amazing that you found the issue that quickly! I did the adjustment here: https://github.com/Hakky54/mutual-tls-ssl/commit/f8bb43863b181818920da1bba4c1c216855d09a5 and the build is passing, see here: https://github.com/Hakky54/mutual-tls-ssl/actions/runs/9206458636 We can close this issue. Thank you for your help!

It seems like I wrongly configured cucumber and spring. But is cucumber more strict in the configuration setup from version 7.10.0 onwords? It seems that my existing setup was not an issue in the past, but maybe not the correct way to setup everything....

mpkorstanje commented 1 month ago

Oh, it was just a guess. But you're welcome!

I'll leave this open for now, ideally Cucumber would catch misconfiguration with a clear exception message. But I don't really understand why what you did here would be wrong - and that doesn't make for a good explanation / instruction.

mpkorstanje commented 1 month ago

Okay. As it turns out, nothing is wrong here. Prior to #2661 cucumber instantiated and initialized the annotated classes. However Spring expected only an instantiated raw bean. As we stopped instantiating, things like AspectJ also stopped working.

Hakky54 commented 1 month ago

Ah, it makes sense now and the additional documentation for this topic in your PR is also helpful. Thank you for further investigating this