问题描述
我在 Gherkin 中有一个类似于以下的步骤:
And the date range options are correct
| startDate | endDate | isDefault | isCurrent |
| 2020-03-02 | 2021-03-01 | false | false |
| 2019-03-02 | 2020-03-01 | false | false |
在步骤定义类中,我尝试使用 Rest Assured 和 Hamcrest 来验证 JSON 响应中的日期范围。
@And("the date range options are correct")
public void validateDateranges(DataTable expectedDateranges) {
String response = getJSONResponse();
List<Map<String,Object>> expected = expectedDateranges.asMaps(String.class,Object.class);
assertthat("Date Ranges are correct",from(response).get("daterangeOptions"),equalTo(expected));
}
但是,这失败并出现以下错误:
Expected: <[{startDate=2020-03-02,endDate=2021-03-01,isDefault=false,isCurrent=false},{startDate=2019-03-02,endDate=2020-03-01,{startDate=2018-03-02,endDate=2019-03-01,endDate=2018-06-17,isDefault=true,{startDate=2017-03-02,endDate=2018-03-01,{startDate=2016-03-02,endDate=2017-03-01,{startDate=2015-08-18,endDate=2016-03-01,isCurrent=false}]>
but: was <[{startDate=2020-03-02,isCurrent=false}]>
at org.hamcrest.MatcherAssert.assertthat(MatcherAssert.java:20)
at scenarios.pagination.AccrualLog.validateDateranges(AccrualLog.java:80)
at ✽.the date range options are correct(file:///.../accrualLog.feature:7)
考虑到这些值看起来都是正确的,我认为这是由于数据类型不匹配 - 布尔字段从 DataTable 作为字符串返回。
除了使用类来表示日期范围之外,还有什么方法可以解决这个问题吗?
解决方法
我找到了解决方案。最后,我创建了自己的 Matcher 实现来检查 Cucumber DataTables:
public class DataTableMatcher extends BaseMatcher<Object> {
private final List<Map<String,String>> expectedValues;
public DataTableMatcher(Object expectedValue) {
this.expectedValues = ((DataTable) expectedValue).asMaps();
}
public boolean matches(Object o) {
List<?> actual = (List<?>) o;
List<Map<String,String>> actualValues = actual.stream().map(this::castRow).collect(Collectors.toList());
return expectedValues.equals(actualValues);
}
private Map<String,String> castRow(Object row) {
Map<String,String> result = new HashMap<>();
Map<?,?> cast = (Map<?,?>) row;
for (Object column : cast.keySet()) {
result.put(column.toString(),cast.get(column).toString());
}
return result;
}
@Override
public void describeTo(Description description) {
description.appendText("It to be right"); //TODO more helpful error message
}
public static Matcher<Object> dataTablesMatch(Object t) {
return new DataTableMatcher(t);
}
}
然后我可以这样使用它:
@And("the date range options are correct")
public void validateDateRanges(DataTable expectedDateRanges) {
String response = getJSONResponse();
assertThat("Date Ranges are correct",from(response).get("dateRangeOptions"),dataTablesMatch(expectedDateRanges));
}
这有效。不过,我很想知道是否有更优雅的解决方案。