使用 REST Assured 检查 HTML 文档

Checking HTML document with REST Assured

我正在尝试使用 REST Assured to check some properties on an HTML document returned by my server. An SSCCE 演示问题如下:

import static com.jayway.restassured.path.xml.config.XmlPathConfig.xmlPathConfig;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;

import com.jayway.restassured.path.xml.XmlPath;

public class HtmlDocumentTest {

  @Test
  public void titleShouldBeHelloWorld() {
    final XmlPath xml = new XmlPath("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
      + "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
      + "<head><title>Hello world</title></head><body></body></html>")
      .using(xmlPathConfig().with().feature("http://apache.org/xml/features/disallow-doctype-decl", false));
    assertThat(xml.get("//title[text()]"), is("Hello world"));
  }
}

现在,此尝试以 com.jayway.restassured.path.xml.exception.XmlPathException: Failed to parse the XML document 结束,原因是关闭所有可能的错误,大约 30 秒后 java.net.ConnectException: Connection timed out

如果我删除带有 xmlPathConfig().with().feature(...) 的行,由于 DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.,测试会立即失败。

如果我从文档中删除 doctype 行,则解析成功但测试因断言错误而失败,“Expected: is "Hello world" but: was <Hello worldnull>”——但是,这显然是一个不同的问题(但请随时提供说明在那一个上……)。无论如何,删除文档类型对我来说不是一个选择。

那么,问题是:如何使用 REST Assured 检查具有文档类型的 HTML 文档的属性?它说 in the documentationREST Assured providers 预定义了解析器,例如 HTML、XML 和 JSON.”,但我似乎无法查找有关如何准确激活和使用 HTML 解析器的任何示例!没有“HtmlPath” class 就像有 XmlPath,例如,超时异常非常令人费解...

我检查了你的代码。问题是 Restassured 的 XmlPath 不是 Xpath,而是使用 属性 访问语法。如果您向示例 HTML 添加正文内容,您会发现您的 XPath 没有做太多事情。查询语言的实际名称是 GPath。以下示例有效,另请注意 CompatibilityMode.HTML 的使用,它具有您需要的正确配置:

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.XmlPath.CompatibilityMode;

public class HtmlDocumentTest {

    @Test
    public void titleShouldBeHelloWorld() {
        XmlPath doc = new XmlPath(
                CompatibilityMode.HTML,
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
                        + "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
                        + "<head><title>Hello world</title></head>"
                        + "<body>some body"
                        + "<div class=\"content\">wrapped</div>"
                        + "<div class=\"content\">wrapped2</div>"
                        + "</body></html>");

        String title = doc.getString("html.head.title");
        String content = doc.getString("html.body.div.find { it.@class == 'content' }");
        String content2 = doc.getString("**.findAll { it.@class == 'content' }[1]");

        assertEquals("Hello world", title);
        assertEquals("wrapped", content);
        assertEquals("wrapped2", content2);
    }
}

如果您使用的是 DSL (given/when/then),那么当响应 content-type header 包含 html 时,将自动使用带有 CompatibilityMode.HTML 的 XmlPath兼容的媒体类型(例如 text/html)。例如,如果 /index.html 包含以下 html 页面:

<html>
    <title>My page</title>
    <body>Something</body>
</html>

然后您可以像这样验证标题和 body:

when().
        get("/index.html").
then().
        statusCode(200).
        body("html.title", equalTo("My page"), 
             "html.body",  equalTo("Something"));

这是带有最新放心 API 的示例代码,即 io.restassured 而不是旧的 jayway.restassured。代码的解释在代码注释中。

//Demo for an api which returns a json string inside html. The json string is just an array of objects.

import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;

import java.util.List;

import static io.restassured.RestAssured.*;

public void testMyApi() {
    Response response =
            when().
                    get("www.myapi.com/data").
            then().
                    extract().
                    response();
    
    String bodyTxt = response.htmlPath().getString("body");//Get the body element of the html response.
    JsonPath jsonObj = new JsonPath(bodyTxt);//helps us to find things in a json string.

    List<String> rootItems = jsonObj.getList("$");//get root element of the json part.

    System.out.println(rootItems);
}