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(List symbols, 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
}