介绍
如今我们会给功能写单元测试,虽然很枯燥,但在规避一些修改造成的bug时,它们发挥着重要的作用。在编写单元测试时,一个绕不开的事情是:写assert。在复杂对象之间做assert,通常会对你关注的字段使用类似assertEquals一类的方法,这些方法在这种情况下会出现问题:你关注的字段没有变更,但其他字段变了。那么,有没有比较方便地对比全部字段的方法?而且能展示出具体哪个字段不一样?
JSONAssert是个不错的选择,它提供四种匹配风格:
| 风格 | 允许额外字段 | 顺序严格 |
|---|---|---|
| STRICT | no | yes |
| LENIENT | yes | no |
| NON_EXTENSIBLE | no | no |
| STRICT_ORDER | yes | yes |
下面是演示。
演示
pom依赖
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.5.0</version>
</dependency>
这里假设得到一个字符串的json,然后我们自己期望的数据是个object,此处引用了lombok和jackson
json
String excepted = "{\n" +
" \"id\": 1,\n" +
" \"name\": \"Shivam\",\n" +
" \"address\": {\n" +
" \"line1\": \"--line 1\",\n" +
" \"line2\": \"--line 2\",\n" +
" \"city\": \"Bengaluru\",\n" +
" \"state\": \"Karnataka\",\n" +
" \"country\": \"India\",\n" +
" \"pincode\": 560037,\n" +
" \"hideMe\":111\n"+
" }\n" +
"}";
object
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
static class Employee {
private int id;
private String name;
private Address address;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
static class Address {
private String line1;
private String line2;
private String city;
private String state;
private String country;
private int pincode;
}
......
Employee employee = Employee.builder()
.id(1)
.name("Shivam")
.address(
Address.builder()
.line1("line 1a")
.city("Bengaluru")
.country("India")
.state("Karnataka")
.pincode(560037)
.build())
.build();
简单比对
测试用例
@Test
public void justAssert() throws JsonProcessingException, JSONException {
ObjectMapper objectMapper = new ObjectMapper();
JSONObject jsonObject = new JSONObject(objectMapper.writeValueAsString(employee));
JSONAssert.assertEquals(excepted,jsonObject, JSONCompareMode.LENIENT);
}
输出
java.lang.AssertionError: address
Expected: hideMe
but none found
; address.line1
Expected: --line 1
got: line 1a
; address.line2
Expected: --line 2
got: null
自定义处理比对结果
这是我非常喜欢的一个功能,你可以按你的想法自行处理比对结果,我这边只是简单地转成了中文
@Test
public void walkResult()throws JsonProcessingException, JSONException{
ObjectMapper objectMapper = new ObjectMapper();
JSONCompareResult result = JSONCompare.compareJSON(excepted,objectMapper.writeValueAsString(employee),JSONCompareMode.LENIENT);
System.out.println("比对失败字段:");
for(FieldComparisonFailure f1 :result.getFieldFailures()){
System.out.println("字段:"+f1.getField()+"\t期望:"+f1.getExpected()+"\t实际:"+f1.getActual());
}
System.out.println("\n比对缺失字段");
for(FieldComparisonFailure f2 :result.getFieldMissing()){
System.out.println("字段:"+f2.getField()+"\t期望:"+f2.getExpected()+"\t实际:"+f2.getActual());
}
System.out.println("\n比对多余字段");
for(FieldComparisonFailure f3 :result.getFieldUnexpected()){
System.out.println("字段:"+f3.getField()+"\t期望:"+f3.getExpected()+"\t实际:"+f3.getActual());
}
}
输出
比对失败字段:
字段:address.line1 期望:--line 1 实际:line 1a
字段:address.line2 期望:--line 2 实际:null
比对缺失字段
字段:address 期望:hideMe 实际:null
比对多余字段