Cucumber not serializing date string from datatable in feature file to a LocalDate field inside my pojo
Asked Answered
S

1

1

Im trying to figure out how to parse date fields from my cucumber feature files in my step definitions.

class Person{ 
  String name
  LocalDate dob
}

scenario: do something with people
Given  list of people:
                     |name|dob|
                     | john| 20-09-2001|

@Given("^list of people:")
public void doSomething(List<Person> people) {

}

Please note i have no access to the Person class, Im sure i have to either write my own converter or register a converter written by someone from some library, after searching around the only options i can see are to change them pojo with a @Transform on the java.time.LocalDate field.

I'm currently getting the following exception

cucumber.runtime.CucumberException:              cucumber.deps.com.thoughtworks.xstream.converters.ConversionException: Cannot deserialize object with new readObject()/writeObject() methods
---- Debugging information ----
class               : java.time.LocalDate
required-type       : java.time.LocalDate
converter-type      : cucumber.deps.com.thoughtworks.xstream.converters.reflection.SerializableConverter
path                : /list/com.pkg.Person/dob

I have tried changing the dateformat to yyyy-MM-dd, that usually works but not on this occasion. I would be gratefull for any pointers on how to setup and register a custom converter

my cucumber dependencies are as follows, i can chane these if required to newer versions if it makes any difference.

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>2.4.0</version>
    </dependency>

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>2.4.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>2.4.0</version>
    </dependency>
Sheepdip answered 29/3, 2018 at 21:26 Comment(0)
M
6

Cucumber does not support automatic conversion of the new java date time classes. But it does support conversion to the old util Date class which is of no use as you do not have write access to the dataobject.

For this to work you will need to use the @XStreamConverters annotation on the test runner. This will add the custom xstream converter to the out of the box converters in cucumber.

@RunWith(Cucumber.class)
@CucumberOptions(plugin = { ""}, tags = { "" }, glue = "stepdefs",
        features = "" ) --> use your own values
@XStreamConverters(@XStreamConverter(LocalDateCon.class))
public class RunSampleTest {

Now the converter class to parse the string into LocalDate and create the collection of dataobjects. This will support dates like "15-05-2016". Just change the DEFAULT_DATE_PATTERN according to your date format.

public class LocalDateCon implements Converter{

    public boolean canConvert(Class type) {
        //return type.equals(LocalDate.class);
        return LocalDate.class.isAssignableFrom(type);
    }

    private static final String            DEFAULT_DATE_PATTERN = "dd-MM-yyyy";
    private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN);

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
        LocalDate  date = (LocalDate) value;
        String result = date.format(DEFAULT_DATE_FORMATTER);
        writer.setValue(result);
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        LocalDate result = LocalDate.parse(reader.getValue(), DEFAULT_DATE_FORMATTER);
        return result;
    }

}

Also you will not be able to use @Transform annotation cleanly as it works only for a single value and not a collection. I used cleanly as one will need to do the object creation in the converter code which is messy.

Malpighiaceous answered 30/3, 2018 at 9:1 Comment(6)
Hi That seems to have worked, So if i want to provide a custom parser for say Person.class i would create a Converter like this. I kept thinking i can create a subtype of AbstractSingleValueConverter and that will work.Sheepdip
Some reason, which I am unable to figure out, extending AbstractSingleValueConverter is not working and throwing the exception u mentioned in the post. Tried googling it and some pointed out it might be a difference in compiler versions. Though when I use AbstractSingleValueConverter subtype with xtreamconverter annotation directly on the localdate field in the dataobject it works.Malpighiaceous
Can you point me to where this approach is documented, im struggling to find thisSheepdip
This is new with cucumber 2.0. Link to the actual changes - github.com/cucumber/cucumber-jvm/pull/1010Malpighiaceous
Interesting i stumbled across that page and skim read it, only now when i have viewed the actual changes, i noticed it looks for instanceOf Converter in order to register the XstreamConverters provided outside the Object. Thnaks for your help.Sheepdip
I needed to do the same for LocalDateTime but I managed thanks to your example. Thanks Grasshopper!Fencer

© 2022 - 2024 — McMap. All rights reserved.