Cucumber V5-V6 feature文件步骤传递含List等集合的复杂对象问题
Cucumber v6 逗号分隔单元格转集合类型解决方案
报错原因
你当前使用的Jackson ObjectMapper默认只能将JSON结构的字符串(如["romance","happy"])转换为集合类型,无法直接识别逗号分隔的普通字符串为List/Set等集合,因此在转换genre列的字符串时抛出ArrayList构造失败的异常。
解决方案
方案1:全局配置自定义反序列化器(适配所有集合类型)
该方案不需要修改现有步骤定义和业务类,全局生效,天然支持List、HashSet等所有Collection接口的实现类:
- 编写自定义集合反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.util.Arrays; import java.util.Collection; public class CommaSeparatedCollectionDeserializer extends StdDeserializer<Collection<?>> { public CommaSeparatedCollectionDeserializer() { super(Collection.class); } @Override public Collection<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, InstantiationException, IllegalAccessException { String content = p.getText().trim(); // 获取目标字段声明的实际集合类型 JavaType targetType = ctxt.getContextualType(); Collection<String> result = (Collection<String>) targetType.getRawClass().newInstance(); // 空值直接返回空集合 if (content.isBlank()) { return result; } // 按逗号分割后逐个去空格加入集合 Arrays.stream(content.split(",")) .map(String::trim) .forEach(result::add); return result; } }
- 调整你的默认转换器配置,注册自定义反序列化器
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import io.cucumber.java.DefaultDataTableCellTransformer; import io.cucumber.java.DefaultDataTableEntryTransformer; import io.cucumber.java.DefaultParameterTransformer; import java.lang.reflect.Type; @DefaultParameterTransformer @DefaultDataTableEntryTransformer(replaceWithEmptyString = "[blank]") @DefaultDataTableCellTransformer public Object transformer(Object fromValue, Type toValueType) { ObjectMapper objectMapper = new ObjectMapper(); // 注册自定义集合反序列化器 SimpleModule module = new SimpleModule(); module.addDeserializer(Collection.class, new CommaSeparatedCollectionDeserializer()); objectMapper.registerModule(module); // 注意:你的Songs类字段名为genres,数据表头为genre,需要给genres字段加@JsonProperty("genre")注解匹配字段 return objectMapper.convertValue(fromValue, objectMapper.constructType(toValueType)); }
方案2:单独为Songs类配置转换器(无全局影响)
如果你不需要全局适配所有集合类型,只想针对当前Songs类做转换,可以直接添加独立的DataTableEntry转换器,代码更简洁:
import io.cucumber.java.DataTableEntryType; import java.util.Arrays; import java.util.stream.Collectors; @DataTableEntryType public Songs convertToSongs(Map<String, String> entry) { return new Songs( entry.get("title"), Arrays.stream(entry.get("genre").split(",")) .map(String::trim) .collect(Collectors.toList()) ); }
其他说明
- 方案1天然支持所有Collection子类型:如果你把Songs类的
List<String> genres改为Set<String> genres,转换器会自动实例化HashSet,自动实现内容去重,不需要额外修改逻辑。 - 小提示:你当前步骤注解里重复写了
Then关键字,建议调整为@Then("The results are as follows:")避免步骤匹配异常。
内容的提问来源于stack exchange,提问作者Fox1987
相关产品推荐
相关产品推荐

