JBehave automatically converts the textual representation of a parameter extracted from the candidate step with the parameter type of the matched method in the Steps class. Let's go back to our example to make this point clear. Consider a single textual step:
Given a stock of symbol STK1 and a threshold of 10.0
which we map to the Java method:
@Given("a stock of symbol $symbol and a threshold of $threshold") public void aStock(String symbol, double threshold) { // ... }
The two arguments which are identified as parameters in matching the textual step to the annotation pattern are: "STK1" and "1.0". These are converted respectively to a String and a double.
If we had comma-separated values, e.g
Given a stock of symbols STK1,STK2 and thresholds of 10.0,20.0
these would handled automatically as well, provided the type of the parameter was a List
@Given("a stock of symbols $symbols and thresholds $thresholds") public void aStock(Listsymbols, List thresholds) { // ... }
More in general, JBehave provides out-of-the-box support for Strings, numbers and the lists thereof.
At the core of the parameter conversion mechanism lies the ParameterConverters facade and the interface:
public static interface ParameterConverter { boolean accept(Type type); Object convertValue(String value, Type type); }
The built-in support for Java types is provided by implementations of this interface. Specifically:
This mechanism then allows for custom converters to be defined too. For example, let's consider the case of date conversion, a rather common one. The step would typically look like:
When a stock of symbol STK1 is traded on 09/09/2009
and the matching step is
@When("a stock of symbol $symbol is traded on $tradedOn") public void aStockIsTradedOn(String symbol, Date tradedOn) { // ... }
Out of the box, JBehave cannot know how to convert the argument value "09/09/2009" to a Date object. Date formats are far from standard. In this case, we want to use the date format "dd/MM/yyyy" and configure the parameter converter for Date type. An implementation of Date converter, backed up a SimpleDateFormat, could be:
public class DateConverter implements ParameterConverter { private final SimpleDateFormat dateFormat; public DateConverter(String dateFormat) { this.dateFormat = new SimpleDateFormat(dateFormat); } public boolean accept(Type type) { if (type instanceof Class>) { return Date.class.isAssignableFrom((Class>) type); } return false; } public Object convertValue(String value, Type type) { try { return dateFormat.parse(value); } catch (ParseException e) { throw new RuntimeException("Could not convert value "+value+" with format "+dateFormat.toPattern()); } } }
Then we configure the use of the newly defined DateConverter in our Steps class:
private static final StepsConfiguration configuration = new StepsConfiguration(); public MySteps(ClassLoader classLoader) { super(configuration); configuration.useParameterConverters(new ParameterConverters( new DateConverter("dd/MM/yyyy))); // define converter for custom type Date }