Reputation: 6516
I want to create custom datatable transformer in cucumber. This is how my feature looks like:
Given board
| o | _ | _ |
| o | _ | _ |
| o | _ | _ |
And I want to put it into custom object. Let's say that it looks like this:
class Board {
private List<List<String>> board;
public Board(List<List<String>> board) {
this.board = board;
}
}
My step definition should look like this:
@Given("^board$")
public void board(Board board) throws Throwable {
// todo
}
Step definition works fine for DataTable
class and List<List<String>>
@Given("^board$")
public void board(DataTable board) throws Throwable {
// this works fine
}
And this also works fine
@Given("^board$")
public void board(List<List<String>> board) throws Throwable {
// this also works fine
}
I tried to find a solution on the internet but without any success. I also tried to create Transformer
but, as I see, it works fine only for strings (I want to use Datatable or List> at the input):
class BoardTransformer extends Transformer<Board> {
@Override
public Board transform(String value) {
// TODO Auto-generated method stub
return null;
}
}
Upvotes: 9
Views: 11424
Reputation: 11
In older version of cucumber, as per your stated 1.2.2, you would have to request a list of your object as each row of the data table (from a feature file perspective) is seen as a different object e.g.
@Given("^board$")
public void board(List<Board> board) throws Throwable {
// process however you want
}
a lot of cucumber has changed from v3 onwards regarding data tables e.g. switching from XStream to Jackson
but as previously advised, upgrade your Cucumber version if possible
Upvotes: 1
Reputation: 12039
In cucumber 3.x you can use the TypeRegistryConfigurer
to inform Cucumber how it should create Board
objects from DataTable
. Because you want to transform the whole table to a single object you have to use a TableTransformer
rather then TableCellTransformer
,TableEntryTransformer
or TableRowTransformer
.
You can place the TypeRegistryConfigurer
anywhere on the glue path.
package io.cucumber.java.test;
import io.cucumber.core.api.TypeRegistryConfigurer;
import io.cucumber.core.api.TypeRegistry;
import io.cucumber.datatable.DataTableType;
import io.cucumber.datatable.TableTransformer;
import java.util.List;
import java.util.Locale;
import static java.util.Locale.ENGLISH;
public class TypeRegistryConfiguration implements TypeRegistryConfigurer {
@Override
public Locale locale() {
return ENGLISH;
}
@Override
public void configureTypeRegistry(TypeRegistry typeRegistry) {
typeRegistry.defineDataTableType(new DataTableType(
Board.class,
(TableTransformer<Board>) table -> new Board(table.cells())));
}
static class Board {
private final List<List<String>> board;
private Board(List<List<String>> board) {
this.board = board;
}
}
}
Upvotes: 4
Reputation: 3915
Assuming the goal is to separate the "nasty parameter transform stuff" from the "actual test code", so that I can use nice objects in my test code, the best I have been able to come up with is to make use of Jackson ObjectMapper (or some other de/serialization lib that supports Map to Object).
For example:
private ObjectMapper objectMapper = new ObjectMapper();
@When("I do some thing with input dataTable")
public void i_do_some_thing_with_input_dataTable(DataTable dataTable) {
List<Map<String,String>> values = dataTable.asMaps(String.class, String.class);
List<MyObject> inputs = values.stream().map(i -> objectMapper.convertValue(i,MyObject.class)).collect(Collectors.toList());
inputs.forEach(i-> {
//Do things with the input.
});
}
You can/should ofcourse wrap this conversion in some nice service class that you can inject into / instantiate in your test.
This code assumes the following:
MyObject
with names that correspond to the headers in the tableMyObject
has appropriate getter/setters for each field.Upvotes: 0
Reputation: 382
If you can go with
@Given("^board$")
public void board(List<List<String>> board) throws Throwable {
...
Why don't you just create your Board object right after
Board board2 = new Board(board);
It doen't look like you need a transformer.
Upvotes: 0