REST Assured 系列汇总 之 REST Assured 70 - Compare JSON Objects Using JSONassert Library
介绍
API 测试,有时需要比较两个 JSON。例如:我们想每次从一个 API返回的结果是一样的,或部分 response body 结果是不变的,就可以直接比较已经存在的 JSON response,省去了写大量逻辑代码去断言。
有许多好的 Java 库可以用来比较,前面我们用 Jackson 库 比较两个 JSONs,本文我们主要了解用 JSONassert 库来比较两个 JSON response。
前提条件
添加 JSONassert 依赖
<!-- https://mvnrepository.com/artifact/org.skyscreamer/jsonassert -->
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
<version>1.5.0</version>
<scope>test</scope>
</dependency>
请先阅读下面文章,了解 JSONassert Java library 基本概念 和不同的比较模式。
Introduction To JsonAssert Library
assertEquals() 方法
JSONassert 提供了很多静态重载的 assertEquals() 方法
Lenient mode
前面的文章我们了解到,在 Lenient 模式中,extensibility 是允许的,没有严格的顺序要求,我们通过例子来了解一下。
比较两个一样的 JSON Object
assertEquals() 方法会 PASS,因为两个 JSON 字符串是相同的。
@Test
public void exactSameJson() throws JSONException {
String jsoNobject1 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\"\r\n" +
"}";
String jsonObject2 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\"\r\n" +
"}";
// Lenient mode - extensible and no strict ordering
JSONAssert.assertEquals(jsoNobject1, jsonObject2, JSONCompareMode.LENIENT);
}
比较两个 JSON Objects,字段相同,只是顺序不同
下面例子,两个 JSON 有相同的字段,字段对应的值也是相同的,但是字段排列顺序不同。因为 Lenient 模式,strict order 是没有应用的,而且 strict order 只对 JSON Array 有意义,而对 JSON objects 没有效果,所以 assertEquals() 会 PASS。
@Test
public void exactSameJsonWIthDifferentOrder() throws JSONException {
String jsoNobject1 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\"\r\n" +
"}";
String jsonObject2 = "{\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"firstName\": \"Amod\"\r\n" +
"}";
// Lenient mode - extensible and no strict ordering but ordering will not be applicable for
// JSON objects
JSONAssert.assertEquals(jsoNobject1, jsonObject2, JSONCompareMode.LENIENT);
}
比较两个 JSONs,字段相同,但是字段对应的值不同
因为值不匹配,assertEquals() 会 FAIL
@Test
public void sameFieldsWithDifferentValues() throws JSONException {
String jsoNobject1 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\"\r\n" +
"}";
String jsonObject2 = "{\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"firstName\": \"Rahul\"\r\n" +
"}";
JSONAssert.assertEquals(jsoNobject1, jsonObject2, JSONCompareMode.LENIENT);
}
结果:
FAILED: sameFieldsWithDifferentValues
java.lang.AssertionError: firstName
Expected: Amod
got: Rahul
比较两个 JSONs,字段相同,但是值的数据类型不同
这个例子比较重要,用 JSONassert 比较 JSONs 要知道 “18” 和 18 是不同的。看上去都是 18,但是数据类型不一样。
@Test
public void unmatchedDataType() throws JSONException {
String jsoNobject1 = "{\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"firstName\": \"Amod\",\r\n" +
" \"age\": \"18\"\r\n" +
"}";
String jsonObject2 = "{\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"firstName\": \"Amod\",\r\n" +
" \"age\": 18\r\n" +
"}";
// First json has 18 as string while second json has 18 as int
JSONAssert.assertEquals(jsoNobject1, jsonObject2, JSONCompareMode.LENIENT);
}
结果:
FAILED: unmatchedDataType
java.lang.AssertionError: age
Expected: 18
got: 18
Strict Mode
如果我们不想选择 extensibility, 而是想准确比较两个 JSONs,我们可以用 strict mode。
@Test
public void strictMatchExample1() throws JSONException {
String jsoNobject1 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\"\r\n" +
"}";
String jsonObject2 = "{\r\n" +
" \"firstName\" : \"Amod\",\r\n" +
" \"lastName\": \"Mahajan\",\r\n" +
" \"age\": 28\r\n" +
"}";
JSONAssert.assertEquals(jsoNobject1, jsonObject2, JSONCompareMode.STRICT);
}
结果:
FAILED: strictMatchExample1
java.lang.AssertionError:
Unexpected: age
用重载 assertEquals() method
前面的例子,assertEquals() 方法接收的都是 JSON 字符串,我们也可以传递 JSONObject 或 JSONArray,这样让你有更多的选择用来比较 JSONs。
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.junit.Test;
public class LinentMatchWithJsonObject {
@Test
public void matchJsonObject() throws JSONException {
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("firstName", "Amod");
jsonObject1.put("lastName", "Mahajan");
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("firstName", "Amod");
jsonObject2.put("lastName", "Mahajan");
JSONAssert.assertEquals(jsonObject1, jsonObject2, JSONCompareMode.LENIENT);
}
}
如果不想用 JSONCompareMode 枚举,也可以用另外一个重载方法 assertEquals() 方法,通过 boolean 参数来传递 mode,默认是非 strict 的,如果想选择 strict,传递 true 值。
assertEquals(JSONObject expected, JSONObject actual, boolean strict)
如果两个 JSONs 不一样,也可以定制化消息:
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONAssert;
import org.testng.annotations.Test;
public class LinentMatchWithJsonObject {
@Test
public void matchJsonObject() throws JSONException {
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("firstName", "Amod");
jsonObject1.put("lastName", "Mahajan");
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("firstName", "Rahul");
jsonObject2.put("lastName", "Mahajan");
//JSONAssert.assertEquals(jsonObject1, jsonObject2, false);
JSONAssert.assertEquals("Jsons are not equal", jsonObject1, jsonObject2, false);
}
}
结果:
FAILED: matchJsonObject
java.lang.AssertionError: Jsons are not equal firstName
Expected: Amod
got: Rahul
Handling Error using try-catch
当比较失败时,会抛出 AssertionError,可以用 catch 来捕获异常。
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONAssert;
import org.testng.annotations.Test;
public class ErrorHandlingJSONassert {
@Test
public void errorHandling() throws JSONException {
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("firstName", "Amod");
jsonObject1.put("lastName", "Mahajan");
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("firstName", "Rahul");
jsonObject2.put("lastName", "Mahajan");
try {
JSONAssert.assertEquals(jsonObject1, jsonObject2, false);
}catch(Error e)
{
System.out.println("Error occured as JSONs are not same.");
}
}
}
结果:
Error occured as JSONs are not same.
PASSED: errorHandling