java调用接口(rest-assured)

参考来源:https://blog.csdn.net/u011622109/article/details/106904955

官网:https://rest-assured.io/

文档翻译: https://iworkh.gitee.io/blog/2020/06/17/java_rest_assured_wiki_info/

一、被测试的接口准备,来自于上面的参考,spring boot框架

响应类

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonDataResult<T> {
        protected boolean success;
        protected String message;
        protected int errorCode = 0;

        @JsonProperty("result")
        protected T data;
}
View Code

实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVo {
    private int id;
    private String name;
    private Date birthday;
    private boolean vip;
}
View Code

controller

import com.example.demo.pojo.JsonDataResult;
import com.example.demo.pojo.UserVo;

import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Random;

@RestController
@RequestMapping("/api/user")
public class UserController {

    @PostMapping("/createUserByParam")
    public JsonDataResult<Boolean> createUserByParam(UserVo userVo) {
        JsonDataResult<Boolean> result = new JsonDataResult<>();
        userVo.setId(new Random().nextInt(50));
        result.setSuccess(true);
        result.setData(true);
        return result;
    }

    @PostMapping("/createUserByJson")
    public JsonDataResult<Boolean> createUserByJson(@RequestBody UserVo userVo) {
        JsonDataResult<Boolean> result = new JsonDataResult<>();
        userVo.setId(new Random().nextInt(100));
        result.setSuccess(true);
        result.setData(true);
        return result;
    }

    @GetMapping("/{id}")
    public JsonDataResult<UserVo> getUser(@PathVariable int id) {
        JsonDataResult<UserVo> result = new JsonDataResult<>();
        String[] hobbies = {"football", "sing"};
        //从数据库查询,省略
        UserVo user = new UserVo(id, "测试名字" + id, new Date(), true);
        result.setSuccess(true);
        result.setData(user);
        return result;
    }

    @PutMapping
    public JsonDataResult<UserVo> updateUser(@RequestBody UserVo userVo) {
        JsonDataResult<UserVo> result = new JsonDataResult<>();
        //从数据库删除,省略
        result.setSuccess(true);
        result.setData(userVo);
        return result;
    }

    @DeleteMapping("/{id}")
    public JsonDataResult<Boolean> delteUser(@PathVariable int id) {
        JsonDataResult<Boolean> result = new JsonDataResult<>();
        //从数据库删除,省略
        result.setSuccess(true);
        result.setData(true);
        return result;
    }
}
View Code

二、依赖,杂七杂八一堆

   <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-path</artifactId>
            <version>4.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>xml-path</artifactId>
            <version>4.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.4.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured-common</artifactId>
            <version>4.4.0</version>
            <scope>compile</scope>
        </dependency>
View Code

三、语法链
given()--when()--then()
1、given 后面,  设置参数、头、认证
2、when() 后面,  请求rest接口,get、post、put、delete等
3、then() 后面,    验证结果。

四、2个静态引用,一个是框架本身,一个是用于校验使用

// 官方推荐静态引用
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

五、入参

 @Test
    public void testParams() {
        // 1、given() 是RestAssured类下一个方法,官方文档强烈推荐使用静态导入语句
// 2、get方法,对应GET请求,这一步已经请求完成了
        // 3、then() 为后面对response消息做判断时做准备
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("userId", "2");
        params.put("id", "14");

        HashMap<String, String> headers = new HashMap<String, String>();
        headers.put("accept-encoding", "gzip,deflate");
        headers.put("accept-language", "zh-CN");

        given().
                // 调用效果:http://jsonplaceholder.typicode.com/posts?id=14&userId=2
                // 这个貌似和params一样的效果
                queryParams(params).
                // params(params).
                // param只能设置一个参数,多调用几次可以多设置几个参数,下面的header类似
                // param("userId", 2).
                // 多个头字段
                headers(headers).
                // header("accept-encoding", "gzip,deflate").
            when().
                // 请求前的log 是打印请求参数信息
                // log().all().
                    get("http://jsonplaceholder.typicode.com/posts").
            then().
                // 请求后的log 是打印响应参数信息
                    log().body();
    }
@Test
    public void testAssert() {
        given().
                // 效果 http://jsonplaceholder.typicode.com/posts/3
                // 把下面地址中的变量替换掉
                    pathParam("section", "posts").
                    pathParam("id", "3").
             when().
                    get("http://jsonplaceholder.typicode.com/{section}/{id}");
} 
 @Test
    public void test0011() {
        UserVo user = new UserVo(1, "zhangsan", new Date(), false);

        given().
                // 直接传入对象
                body(user).
                // 两种设置入参类型
                header("Content-Type", "application/json; charset=utf-8").
                // contentType("application/json; charset=utf-8");
            when().
                post("/api/user/createUserByParam");
}

六、响应信息处理

    @Test
    public void test001() {
        // 这里没有设置baseurl,但是依然请求成功了。因为框架有默认的url:http://localhost:8080
        Response response = get("/api/user/3");
        // 使用 as 将响应转化为我们需要的对象
        JsonDataResult j = response.as(JsonDataResult.class);
        // 拿到响应后也可以用testng本身的断言
        Assert.assertEquals(j.isSuccess(),true);
    }
 @Test
    public void testResponse() {
        // 在没有参数设置的前提下,可以直接请求,拿到响应
        Response r = get("https://reqres.in/api/users/2");

        System.out.println("直接获取的响应结果:" + r.asString());
        System.out.println("获取请求头:" + r.getHeaders());
        System.out.println("获取请求头某个字段:" + r.getHeader("Content-Type"));
        System.out.println("获取cookies:" +r.cookies());
        System.out.println("毫秒:" + r.time());
        System.out.println("毫秒,会损失精度:" + r.timeIn(TimeUnit.SECONDS));

        Integer id = r.
                then().
                // json、xm都可以使用xpath路径
                body("data.id", is(2)).
                // 通过extract().path() 摘取内容
                extract().
                path("data.id");

        Response response = r.
                then().
                extract().
                response();
        System.out.println("间接获取到的响应和直接获取的响应比较:" + ( response == r ));
        System.out.println("间接获取到的id和直接获取的id比较:" + ( id == r.path("data.id") ));
    }

七、框架自带的响应断言

    @Test
    public void testAssert() {
        given().
                    pathParam("section", "posts").
                    pathParam("id", "3").
                when().
                    get("http://jsonplaceholder.typicode.com/{section}/{id}").
                then().
                // 下面的断言是线性断言,一旦某个断言失败,后面就不会继续执行
                //断言200
                    statusCode(200).
                // 断言返回的格式对象,例如XML、HTML、TEXT等
                    contentType(ContentType.JSON).
                // 断言响应头字段,header单个,headers多个
                    header("Content-Type", "application/json; charset=utf-8").
                    headers("Content-Type", "application/json; charset=utf-8", "Connection", "keep-alive").
                // Matchers提供了很多匹配方式,equalTo、containsString。hasItem、hasItems这2个我没用成功
                    body(containsString("ea molestias quasi exercitationem")).
                    body("userId", equalTo(1)).

                // body("title", hasItem("ea molestias quasi exercitationem repellat qui ipsa sit aut")).
                // 不同节点相同的key有对应的value,例如:{{"title": "value1"},{"title": "value2"}},
                // 则不能使用equalTo、hasItem,可以使用hasItems(要求把所有的value列出来)
                // body("title", hasItems("ea molestias quasi exercitationem repellat qui ipsa sit aut")).

                // 断言响应时间小于2000毫秒,参数类型是long
                   time(lessThan(2000L)).
                log().body();
    }

八、base信息设置、请求封装RequestSpecification、响应封装ResponseSpecification

public class TC41 {
    RequestSpecification requestSpc;
    ResponseSpecification responseSpc;

    @BeforeClass
    public void setup() {
        // 这里设置了 baseURI、basePath,后面get则不需要再填这2个信息
        RestAssured.baseURI = "http://jsonplaceholder.typicode.com";
        // RestAssured.port = 80;
        RestAssured.basePath = "/posts";
        // 恢复成默认设置
        // RestAssured.reset();

        //  利用RequestSpecification对象来封装一些请求数据
        RequestSpecBuilder builder = new RequestSpecBuilder();
        builder.addParam("userId", "2");
        builder.addHeader("Accept-Encoding", "gzip, deflate");
        requestSpc = builder.build();

        //  利用ResponseSpecification对象来封装一些响应判断的数据
        ResponseSpecBuilder rb = new ResponseSpecBuilder();
        rb.expectStatusCode(200);
        rb.expectHeader("Content-Type", "application/json; charset=utf-8");
        rb.expectHeader("Cache-Control", "max-age=43200");
        responseSpc = rb.build();
   }

    @Test
    public void test1() {
        given().
                spec(requestSpc).log().all().
                when().
                get().
                then().
                spec(responseSpc).
                // 如果错误就打印日志
                log().ifError();
    }
}

九、其他内容

public class TestBase {

    public static RequestSpecification httpRequest;
    public static Response response;
    public Logger logger;

    public static String serverHost;
    public static String port;

    // 静态代码块,随着类的加载而执行,而且只执行一次
    static {
        // 用于加载properties文件,入参不需要文件扩展名.properties
        ResourceBundle rb = ResourceBundle.getBundle("config");
        serverHost = rb.getString("Host");
        port = rb.getString("Port");
    }

    @BeforeClass
    public void setup() {
        String className = this.getClass().getName();
        logger = Logger.getLogger(className);

//        PropertyConfigurator.configure("log4j.properties");
//        logger.setLevel(Level.DEBUG);
//        logger.info("host: " + serverHost);
//        logger.info("port: " + port);
    }

}
一个只会点点点的测试,有疑问可以在测试群(群号:330405140)问我
原文地址:https://www.cnblogs.com/yinwenbin/p/15366943.html