Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of BeforeAll/AfterAll in Kotlin-based Cucumber suite does not work as expected #2934

Open
ejbartelds opened this issue Oct 23, 2024 · 6 comments
Labels
πŸ“– documentation Improvements or additions to documentation
Milestone

Comments

@ejbartelds
Copy link

ejbartelds commented Oct 23, 2024

πŸ‘“ What did you see?

@BeforeAll in a Kotlin-based Cucumber suite did not work as expected, even though placed in a companion object and annotated @JvmStatic

βœ… What did you expect to see?

I expected the @JvmStatic and @BeforeAll annotated method to be picked up by Cucumber without problems, as a before-all initializer method.

πŸ“¦ Which tool/library version are you using?

cucumber-java 7.20.1 kotlin 2.0.x

πŸ”¬ How could we reproduce it?

See screenhots: in Kotlin, write a suite or a test and have a beforeAll method. See the error appear.
Debug this and set a breakpoint in io.cucumber.java.MethodScanner::scan ; you'll see the beforeAll method is "seen" twice, once as a static final method (whish is OK) and once as a non-final method (in the companion object), which triggers the error.

image
image

πŸ“š Any additional context?

No response

@mpkorstanje
Copy link
Contributor

As a work around could you check if it works when you declare the functions at package level instead?

@ejbartelds
Copy link
Author

Ah, why didn't I think of that... A package method does indeed work, and is a viable workaround (for me at least). Thank you for the suggestion.

@mpkorstanje
Copy link
Contributor

Looks like it is also still impossible to accurately detect companion objects in Java without depending on kotlin-reflect.

So probably worth adding a note to the documentation of cucumber-java about this.

@mpkorstanje mpkorstanje added the πŸ“– documentation Improvements or additions to documentation label Oct 24, 2024
@mpkorstanje mpkorstanje added this to the v7.x.x milestone Jan 16, 2025
@CraftyFella
Copy link

CraftyFella commented Jan 20, 2025

I found this also works

object AnObject {
    
    @BeforeAll
    @JvmStatic
    fun beforeAll() {
        // code here
    }

    @AfterAll
    @JvmStatic
    fun afterAll() {
        // code here
    }
}

You can also have a class inside an object such as this:

object AnObject {
    
    @BeforeAll
    @JvmStatic
    fun beforeAll() {
        // code here
    }

    @AfterAll
    @JvmStatic
    fun afterAll() {
        // code here
    }
    class AClass {
        @Before
        fun beforeEachScenario(scenario: Scenario) {
            // code here
        }
    }
}

Which does allow you have reference private vals and vars inside the parent object.

@CraftyFella
Copy link

CraftyFella commented Jan 20, 2025

It would be great to be able to mix @BeforeAll and @before in the same kotlin class using the companion object, however as the original poster @ejbartelds pointed out, this results in an exception.

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.example.Hooks$Companion.beforeAll()
class Hooks {

    @Before
    fun beforeEachScenario(scenario: Scenario) {
        // Use private val in before hook
        assert(setInBeforeAll == 1)
    }

    companion object {
        
        private var setInBeforeAll: Int = 0

        @BeforeAll
        @JvmStatic
        fun beforeAll() {
            setInBeforeAll = 1
        }
        
        @AfterAll
        @JvmStatic
        fun afterAll() {
            // code here
        }
    }
}

This would allow you to have private values in the companion object that can be used in the @before steps.

@mpkorstanje
Copy link
Contributor

@CraftyFella unfortunately it is not possible to access a companion object without kotlin-reflect. So unless someone makes a dedicated Kotlin backed that will not be possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
πŸ“– documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants