Roddy of the Frozen Peas
Roddy of the Frozen Peas

Reputation: 15179

Cucumber-java won't use custom @ParameterType

I have a very old cucumber-java project (v. 1.2.2) that I'm trying to update to use the current version (6.10.4). For the most part it's going well, but I'm having trouble converting an old step definition which used the @Delimiter annotation to use a custom parameter type.

This was the old step definition using the delimiter:

@Then("^there are error messages: \"(.*)\"$")
public void assertAllMessages(@Delimiter("; ") List<String> messages) throws Exception {
  // ...    
}

Since @Delimiter was removed when XStream support was removed from cucumber-java, the documentation says to replace it with a custom @ParameterType. Fair enough. I wrote this one, which should be sufficient to identify a string representation of a semi-colon-separated list and convert it to a List<String>:

@ParameterType("(?:.+;)+.+")
public List<String> stringList(String raw) {
    String[] values = raw.split(";");
    return Arrays.asList(values);
}

And then I removed the @Delimiter from the step definition, but left it otherwise as-is.

However when I run my test, it fails and indicates that I should register a parameter type for List:

Caused by: java.lang.IllegalArgumentException: Can't transform 'foo; bar; baz' to java.util.List<java.lang.String>
BuiltInParameterTransformer only supports a limited number of class types
Consider using a different object mapper or register a parameter type for java.util.List<java.lang.String>
    at io.cucumber.cucumberexpressions.BuiltInParameterTransformer.createIllegalArgumentException(BuiltInParameterTransformer.java:114)
    at io.cucumber.cucumberexpressions.BuiltInParameterTransformer.doTransform(BuiltInParameterTransformer.java:33)
    at io.cucumber.cucumberexpressions.BuiltInParameterTransformer.transform(BuiltInParameterTransformer.java:22)
    at io.cucumber.cucumberexpressions.RegularExpression.lambda$match$0(RegularExpression.java:66)
    at io.cucumber.cucumberexpressions.ParameterType$TransformerAdaptor.transform(ParameterType.java:268)
    at io.cucumber.cucumberexpressions.ParameterType.transform(ParameterType.java:233)
    ... 47 more

I know that it has successfully picked up my custom parameter type, because it's in the same file as the step definition. (Further if I create another copy elsewhere in the glue directory, it complains there's already a parameter type named "stringList" registered.)

I also tried changing the regex to just @ParameterType(".*"), but it made no difference.

How do I get Cucumber to use my custom parameter type for converting a string into a List<String>?


Upvotes: 6

Views: 12170

Answers (3)

Alexey R.
Alexey R.

Reputation: 8676

Assume you have this feature file:

Feature: test

  Scenario: test scenario
    Given: This string: foo; bar; baz

So, to have a proper use of custom parameter types you have to assure two things:

  1. Proper step definition. Your step definition has to be defined as a Cucumber Expression (not regular expression).
@Given("This string: {list}")
public void givenThisString(List<String> myList){
    System.out.println(myList);
}
  1. Proper parameter type. A parameter type defined within some glued class:
@ParameterType("([^;]+);?")
public List<String> list(String[] vals){
    return Arrays.asList(vals);
}

Put your attention at that in your step definition you refer to parameter type as {list} so that Cucumber knows where to take a parser. If you do not specify type name explicitly through annotation value, Cucumber takes the type name as the name of a method you have annotated with @ParameterType

Upvotes: 2

Kirill
Kirill

Reputation: 6036

Feature-file. Delimiter is ";". Examples with and without spaces.

Feature: List of strings testing

  Scenario:
    Given a list of names Anna; Ken; Oleg; Piter
    Given a list of names Anna;Ken;Oleg;Piter
    Given a list of names Anna;    Ken   ; Oleg; Piter

Steps:

@Given("a list of names {names}")
public void getListOfNames(List<String> names) {
    for (String n : names) {
        System.out.println("|" + n + "|");
    }
}

@ParameterType(".*")
public List<String> names(String s){
    return Arrays.asList(s.split("\\s*;\\s*"));
}

Cucumber version: 7.18.0

Upvotes: 0

M.P. Korstanje
M.P. Korstanje

Reputation: 12039

Parameter types are part of cucumber-expressions. So instead of writing a regex you should either use a cucumber-expression or use the exact regex from the parameter type in your regular expression.

@ParameterType("(?:.+;)+.+")
public List<String> stringList(String raw) {
    String[] values = raw.split(";");
    return Arrays.asList(values);
}


@Then("there are error messages: \"{stringList}\"")
public void assertAllMessages(@Delimiter("; ") List<String> messages) throws Exception {
  // ...    
}

Upvotes: 1

Related Questions