Parameter Converters

Automatic conversion of textual values to Java objects

JBehave automatically converts the textual representation of a parameter extracted from the step with the parameter type of the matched method in the steps instance class. Let's go back to our example to make this point clear: the textual step

    Given a stock of symbol STK1 and a threshold of 10.0

would map to the Java method

    @Given("a stock of symbol $symbol and a threshold of $threshold")
    public void stock(String symbol, double threshold) {
        // ...
    }

where 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

Another common use case is that of date conversion. 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) {
        // ...
    }

Built-in parameter converters

JBehave provides out-of-the-box support for several types.

At the core of the parameter conversion mechanism lies the ParameterConverters facade. The built-in support for Java types is provided by implementations of this interface. Specifically:

Built-in conversion for the following Java 8 Date/Time types is implemented using generic FunctionalParameterConverter:

JBehave supports automatic conversion to collections if corresponding element type converter is present. For example, having NumberConverter conversion to List<Number> is performed automatically without specifying extra converters. By default blank values are converted to empty collections of the corresponding types.

Collection type mapping is following:

Parameter type Resulting object type
List ArrayList
Set HashSet
SortedSet TreeSet
NavigableSet TreeSet
Any implementation of Collection having constructor without arguments Corresponding implementation type

Customising parameter converters

To customise built-in parameter converters, simply re-add the instances with the customised configuration, as the newly added instances will take precedence over the default ones:

Defining parameter converters

Users can define their own custom parameter converters by implementing the ParameterConverter interface or by extending the class AbstractParameterConverter or the class AbstractListParameterConverter.

Let's consider the use case where we have persistable objects accessible via persister interface from a String identifier. Then a custom parameter converter may come in very handy so that the lookup of the persistable object is done behind the scenes and does not get in the way of the step implementation. E.g. given the converter:

the step

    Given a trader of name Mauro

would map to the method:

    @Given("a trader of name $name")
    public void trader(Trader trader) {
        // Trader object is provided to the method as parameter
    }

Annotated methods as parameter converters

In some cases defining the converter in Configuration is not an option as the conversion is much more dynamical in nature. In this case, one can annotated Steps method to act as parameter converters when annotated by @AsParameterConverter:

    public MySteps() {
        // Method used as dynamical parameter converter
        @AsParameterConverter
        public Trader createTrader(String name){
            return traderPersister.retrieveTrader(name);
        }
    
    }

The parameter converter configuration is done in the AbstractStepsFactory so you can use any implementation of InjectableStepsFactory that extends the abstract implementation, e.g.:

    @RunWith(JUnitReportingRunner.class)
    public MyStory extends JUnitStory {
        @Override
        public InjectableStepsFactory stepsFactory() {
            return new InstanceStepsFactory(configuration(), new MySteps(), new BeforeAfterSteps());
        }
    }