Cucumber-jvm: Enum conversion not working: IllegalArgumentException: argument type mismatch for step argument

Created on 12 Jun 2018  路  21Comments  路  Source: cucumber/cucumber-jvm

Summary

Regression between 3.0.2 and 2.4.0 breaks converting enum parameters of steps

Expected Behavior

After reverting to 2.4.0:

> Task :cucumber
Feature: Calculations

  Scenario: Divide              # src/test/resources/calculation.feature:2
Doing Division
    When Division is calculated # CalculationStepdefs.splitInfoPfShiftIsSelected(CalculationType)

1 Scenarios (1 passed)
1 Steps (1 passed)

Current Behavior

~~~

Task :cucumber FAILED
Feature: Calculations

Scenario: Divide # src/test/resources/calculation.feature:2
When Division is calculated # CalculationStepdefs.splitInfoPfShiftIsSelected(CalculationType)
cucumber.runtime.CucumberException: Failed to invoke com.example.CalculationStepdefs.splitInfoPfShiftIsSelected(CalculationType) in file:/home/piotr-kubowicz/temp/bugs/cucumber3/build/classes/java/test/, caused by java.lang.IllegalArgumentException: argument type mismatch
at cucumber.runtime.Utils$1.call(Utils.java:29)
at cucumber.runtime.Timeout.timeout(Timeout.java:16)
at cucumber.runtime.Utils.invoke(Utils.java:20)
at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:48)
at cucumber.runtime.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:50)
at cucumber.runner.TestStep.executeStep(TestStep.java:55)
at cucumber.runner.TestStep.run(TestStep.java:42)
at cucumber.runner.PickleStepTestStep.run(PickleStepTestStep.java:53)
at cucumber.runner.TestCase.run(TestCase.java:47)
at cucumber.runner.Runner.runPickle(Runner.java:44)
at cucumber.runtime.Runtime.runFeature(Runtime.java:120)
at cucumber.runtime.Runtime.run(Runtime.java:106)
at cucumber.api.cli.Main.run(Main.java:35)
at cucumber.api.cli.Main.main(Main.java:18)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
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 cucumber.runtime.Utils$1.call(Utils.java:26)
... 13 more
~~~

Possible Solution


Steps to Reproduce (for bugs)

src/test/resources/calculation.feature

Feature: Calculations
  Scenario: Divide
    When Division is calculated
package com.example;

import cucumber.api.java.en.When;

public class CalculationStepdefs {

    @When("([\\S]+) is calculated")
    public void splitInfoPfShiftIsSelected(CalculationType calculationType) {
        System.out.println("Doing " + calculationType);
    }
}
package com.example;

public enum CalculationType {
    Multiplication,
    Division
}

build.gradle

plugins { id 'java-library' }

def cucumberVersion = '3.0.2'
dependencies {
    testImplementation "io.cucumber:cucumber-java8:$cucumberVersion"
}

repositories {
    jcenter()
}

task cucumber() {
    dependsOn testClasses
    doLast {
        javaexec {
            main = "cucumber.api.cli.Main"
            classpath = configurations.testRuntimeClasspath + sourceSets.main.output + sourceSets.test.output
            args = ['--plugin', 'pretty', '--glue', 'com.example', 'src/test/resources']
        }
    }
}
build.dependsOn cucumber

Context & Motivation

This blocks me from upgrading to 3.0.2.

Your Environment

Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Ubuntu 17.10

All 21 comments

You need to register a ParameterType in a class which implements TypeRegistryConfigurer kept in the gluepath. Something similar to - registry.defineParameterType(new ParameterType<>("opertype", ".*?", CalculationType.class, (String cal) -> CalculationType.valueOf(cal))); Refer to this, especially "Custom Parameter Types" section - https://cucumber.io/docs/cucumber/cucumber-expressions/#custom-parameter-types

@grasshopper7 enum conversion should work out of the box, so no explicit parameter type should be necessary.

@pkubowicz can you prepare a Minimal, Complete, and Verifiable example in a git repo please?

@aslakhellesoy I stand corrected. I jumped the gun with explicit ParameterType. Tested without it and it worked. Thanks

Hi @grasshopper7 - Would you please consider joining us on Slack? (You can get an account here Would love to have you, I'm sure you could help people out!

@grasshopper7 no I jumped the gun and you were right :-). Enum support is not built-in.

@pkubowicz you do need to define your own parameter type:

public class MyTypes implements TypeRegistryConfigurer {
    @Override
    public void configureTypeRegistry(TypeRegistry typeRegistry) {
        typeRegistry.defineParameterType(new ParameterType<>(
            "calctype", 
            "\\w+", 
            CalculationType.class, 
            (Transformer) (arg) -> CalculationType.valueOf(arg)
        ));
    }

    @Override
    public Locale locale() {
        return ENGLISH;
    }
}

This also allows you to use Cucumber Expressions:

@When("{calctype} is calculated")

Does that work for you @pkubowicz?

Tested without it and it worked.

Now I'm really confused. You managed to have Cucumber convert to an enum without an explicit parameter type? Can you share the code for that?

@aslakhellesoy This worked fine (without any custom conversion code) in 2.4.0 so I consider this a regression bug or at least a breaking change. Change log for release 3 did not mention anything similar.

@aslakhellesoy Ooops for the confusion. I ran the code on version 2.4 by accident and it worked. Tried on 3.0.2 and it bombed. Guess ParameterType is needed.

@mlvandijk Thanks for the invite. Signed up.

@aslakhellesoy This worked fine (without any custom conversion code) in 2.4.0 so I consider this a regression bug or at least a breaking change. Change log for release 3 did not mention anything similar.

This was one of the automagic transformations provided by XStream. With the removal of XStream the magic is gone.

edit: Yes, I realize this means absolutely nothing if you're not familiar with the internals of Cucumber.

Hi,
I've recently upgraded to v3.0.2 from 2.4.0 and have come across the same problem.
Is out of the box support for enums something that will return or is this not planned?
I see there's a release candidate for v4.0.0 will the issue be fixed in this version?

This is my proposed solution: https://github.com/cucumber/cucumber/pull/423

You still have to define parameter types, but creating them is easy: ParameterType.fromEnum(enumClass)

WDYT?

Yes that would make things easier thanks.

@aslakhellesoy https://github.com/cucumber/cucumber/pull/423 has been merged. Can you run the release script?

cucumber/cucumber#423 has been released and added to cucumber-jvm.

Actually that is just the monorepo playing tricks

cucumber/cucumber#423 is not released yet.

Actually that is just the monorepo playing tricks

What do you mean?

The commit with the fix has a descendant tagged with a release version. But it was the release of datatable not cucumber expressions. Hence the confusion.

In which version of cucumber-jvm8 this fix will be released?

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings