REST Assured 55 - JSON Schema Validation In Rest Assured

REST Assured 系列汇总 之 REST Assured 55 - JSON Schema Validation In Rest Assured

前提条件

添加 rest assured 依赖包

<!-- REST Assured -->
<dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>4.4.0</version>
</dependency>

添加 json-schema-validator 依赖包
Rest Assured 自 2.1.0 版本起支持 JSON Schema validatation。为了使用这个功能,我们需要添加 “json-schema-validator” Java 库。

<!-- json schema validation -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>4.3.0</version>
</dependency>

当你在 Maven central repo 上搜索 json-schema-validator 时,会出现许多相同名字的库。确保 groupId 是 io.rest-assured

Class JsonSchemaValidator

JsonSchemaValidator 类提供了许多重载的静态的方法来执行 JSON schema 校验。

public static JsonSchemaValidator matchesJsonSchemaInClasspath(String pathToSchemaInClasspath) – Creates a Hamcrest matcher that validates that a JSON document conforms to the JSON schema provided to this method.

public static JsonSchemaValidator matchesJsonSchema(File file) – Creates a Hamcrest matcher that validates that a JSON document conforms to the JSON schema provided to this method.

如果将 JSON Schema 文件保存在项目的 resource folder 或 src/test/resources maven 项目,就可以直接用 matchesJsonSchemaInClasspath() 方法,只要传递 JSON Schema 文件名。如果 JSON Schema 文件存储在项目的不同地方或外部项目中,可以用 matchesJsonSchema() 方法。

Asserting JSON response against JSON Schema

Create JSON Schema
我们用到前一篇文章中相同的 JSON Schema,这个 JSON Schema 是基于 Restful Booker – Auth API 生成的。把这个 JSON Schema 存放在 src/test/resources。

AuthJsonSchema.json

{
    
    
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {
    
    },
    "examples": [
        {
    
    
            "token": "abc123"
        }
    ],
    "required": [
        "token"
    ],
    "properties": {
    
    
        "token": {
    
    
            "$id": "#/properties/token",
            "type": "string",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}

在这里插入图片描述

Performing JSON Schema validation using matchesJsonSchemaInClasspath()

我们也可以直接在 body(Matcher matcher) 来调用 schema validator 方法。你可能会想到 JSON Schema validator 方法的返回类型是 JsonSchemaValidator, 怎么可以在 body(Matcher matcher) 方法调用呢。这是因为多层继承。 JsonSchemaValidator 类是间接实现 Matcher 接口。

import org.hamcrest.Matchers;
import org.junit.Test;
 
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.module.jsv.JsonSchemaValidator;
 
public class VerifyJsonSchema {
    
    
 
	@Test
	public void verifyJsonSchema() {
    
    
		
		String jsonStringPayload = "{\"username\" : \"admin\",\"password\" : \"password123\"}";
 
		// GIVEN
		RestAssured
			.given()
				.baseUri("https://restful-booker.herokuapp.com/auth")
				.contentType(ContentType.JSON)
				.body(jsonStringPayload)
		// WHEN
			.when()
				.post()
		// THEN
			.then()
				.assertThat()
				.statusCode(200)
				.body("token", Matchers.notNullValue())
				.body(JsonSchemaValidator.matchesJsonSchemaInClasspath("AuthJsonSchema.json"));
	}
 
}

上面的测试会成功,做一些改动让期望的 JSON Schema 验证失败。

Adding extra required properties
上面 response 里只返回一个属性 “token”,我们在加一个新的属性 “nonExistingProperty” 在 JSON Schema “required” 部分:

{
    
    
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {
    
    },
    "examples": [
        {
    
    
            "token": "abc123"
        }
    ],
    "required": [
        "token",
        "nonExistingProperty"
    ],
    "properties": {
    
    
        "token": {
    
    
            "$id": "#/properties/token",
            "type": "string",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}

失败
从 log 里可以看出一个必要的字段 “nonExistingProperty” 缺失了。

required: ["nonExistingProperty","token"] missing: ["nonExistingProperty"]

java.lang.AssertionError: 1 expectation failed.
Response body doesn't match expectation.
Expected: The content to match the given JSON schema.
warning: the following keywords are unknown and will be ignored: [$id, examples]
    level: "warning"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":""}
    domain: "syntax"
    ignored: ["$id","examples"]
warning: the following keywords are unknown and will be ignored: [$id, examples]
    level: "warning"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":"/properties/token"}
    domain: "syntax"
    ignored: ["$id","examples"]
error: object has missing required properties (["nonExistingProperty"])
    level: "error"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":""}
    instance: {
    
    "pointer":""}
    domain: "validation"
    keyword: "required"
    required: ["nonExistingProperty","token"]
    missing: ["nonExistingProperty"]

  Actual: [token:11b60187aad762d]
...............................

Change the data type of properties
属性 “token” 字段的值类型是 string,我们把它改成 integer 类型 “type”: “integer”,看看校验结果。

{
    
    
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {
    
    },
    "examples": [
        {
    
    
            "token": "abc123"
        }
    ],
    "required": [
        "token"
    ],
    "properties": {
    
    
        "token": {
    
    
            "$id": "#/properties/token",
            "type": "integer",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}
ditionalProperties": true
}

类型匹配失败

error: instance type (string) does not match any allowed primitive type (allowed: ["integer"])

java.lang.AssertionError: 1 expectation failed.
Response body doesn't match expectation.
Expected: The content to match the given JSON schema.
warning: the following keywords are unknown and will be ignored: [$id, examples]
    level: "warning"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":""}
    domain: "syntax"
    ignored: ["$id","examples"]
warning: the following keywords are unknown and will be ignored: [$id, examples]
    level: "warning"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":"/properties/token"}
    domain: "syntax"
    ignored: ["$id","examples"]
warning: the following keywords are unknown and will be ignored: [$id, examples]
    level: "warning"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":"/properties/token"}
    domain: "syntax"
    ignored: ["$id","examples"]
error: instance type (string) does not match any allowed primitive type (allowed: ["integer"])
    level: "error"
    schema: {
    
    "loadingURI":"file:/C:/ForKelly/Automation/RestAssuredDemo/target/test-classes/AuthJsonSchema.json#","pointer":"/properties/token"}
    instance: {
    
    "pointer":"/token"}
    domain: "validation"
    keyword: "type"
    found: "string"
    expected: ["integer"]

  Actual: [token:88a742f48f20b7c]

Performing JSON Schema validation using matchesJsonSchema()

上面的例子中我们将 JSON Schema 文件放在 src/test/resources folder 下,可以使用 matchesJsonSchemaInClasspath() 方法。如果我们将 JSON Schema 文件不是放在 resource 文件夹下,那么就不能使用 matchesJsonSchemaInClasspath() 这个方法,否则会抛出 IllegalArgumentException 异常。

注意:前面提到 schema 文件放在 src/test/resources folder 下,其实你也可以将 schema 文件放在 src/main/resources folder 下。测试类可以放在 src/main/java 或 src/test/java,但是作为好的实践标准,我们最好将测试相关的类放在 src/test/java folder 下。最好在 pom.xml 添加依赖包时移除 tag,这样就能避免不必要的范围限制。
例如:

<!-- json schema validation -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>4.3.0</version>
    <scope>test</scope>
</dependency>

移除 tag

<!-- json schema validation -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>4.3.0</version>
</dependency>

如果将 schema 文件不是放在 resource folder 下,我们就要用到另外一个静态方法 matchesJsonSchema() ,需要传一个完整的 JSON Schema 文件路径。

import java.io.File;
 
import org.hamcrest.Matchers;
import org.junit.Test;
 
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.module.jsv.JsonSchemaValidator;
 
public class VerifyJsonSchemaNonResource {
    
    
 
	@Test
	public void verifyJsonSchema() {
    
    
		
		String jsonStringPayload = "{\"username\" : \"admin\",\"password\" : \"password123\"}";
 
		// GIVEN
		RestAssured
			.given()
				.baseUri("https://restful-booker.herokuapp.com/auth")
				.contentType(ContentType.JSON)
				.body(jsonStringPayload)
		// WHEN
			.when()
				.post()
		// THEN
			.then()
				.assertThat()
				.statusCode(200)
				.body("token", Matchers.notNullValue())
				.body(JsonSchemaValidator.matchesJsonSchema(new File("C:\\Users\\kkk\\git\\master\\src\\test\\java\\JsonSchema\\schema.json")));
	}

}

记住:matchesJsonSchema 方法的参数是一个 File 对象,不是文件的完整路径 string 类型。matchesJsonSchema() 期望的 JSON schema 是一个 string 而不是一个 文件路径的 string.

总结

  1. 要执行 JSON Schema 校验,必须添加 “json-schema-validator” Java 库。
  2. JsonSchemaValidator 类提供静态的方法 methods matchesJsonSchema() 和 matchesJsonSchemaInClasspath() 来进行 JSON Schema 校验。
  3. 如果将期望的 JSON Schema 文件放在 resource folder 下,那么可以使用 matchesJsonSchemaInClasspath() 方法。如果不是放在 resource folder 下,则要使用 matchesJsonSchema() 方法。

Guess you like

Origin blog.csdn.net/wumingxiaoyao/article/details/120584799