REST Assured案例

wen java案例 2

本文目录导读:

REST Assured案例

  1. 基础GET请求测试
  2. POST请求创建资源
  3. PUT/PATCH/DELETE操作
  4. 高级响应验证
  5. 认证和Token处理
  6. 完整测试框架示例
  7. 文件上传和下载
  8. 日志和调试
  9. 并行测试和性能优化
  10. 数据驱动测试

我来为您提供几个REST Assured的实战案例,从基础到高级应用。

基础GET请求测试

简单GET请求

import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class BasicGETTests {
    @Test
    public void testGetSingleUser() {
        // 设置基础URL
        RestAssured.baseURI = "https://api.example.com";
        // 发送GET请求并验证响应
        given()
            .header("Content-Type", "application/json")
        .when()
            .get("/users/1")
        .then()
            .statusCode(200)
            .body("id", equalTo(1))
            .body("name", equalTo("John Doe"))
            .body("email", containsString("@example.com"));
    }
    @Test
    public void testGetAllUsers() {
        given()
            .queryParam("page", 1)
            .queryParam("limit", 10)
        .when()
            .get("/users")
        .then()
            .statusCode(200)
            .body("data.size()", greaterThan(0))
            .body("total", greaterThan(0));
    }
}

POST请求创建资源

import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import java.util.HashMap;
import java.util.Map;
public class POSTRequestsTests {
    @Test
    public void testCreateUser() {
        // 使用Map创建请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("name", "Jane Smith");
        requestBody.put("email", "jane@example.com");
        requestBody.put("age", 28);
        given()
            .contentType(ContentType.JSON)
            .body(requestBody)
        .when()
            .post("/users")
        .then()
            .statusCode(201)
            .body("id", notNullValue())
            .body("name", equalTo("Jane Smith"));
    }
    @Test
    public void testCreateUserWithPojo() {
        // 使用POJO对象
        User user = new User();
        user.setName("Bob Johnson");
        user.setEmail("bob@example.com");
        user.setAge(32);
        given()
            .contentType(ContentType.JSON)
            .body(user)
        .when()
            .post("/users")
        .then()
            .statusCode(201)
            .body("name", equalTo("Bob Johnson"));
    }
    // POJO类
    static class User {
        private String name;
        private String email;
        private int age;
        // getters和setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        public int getAge() { return age; }
        public void setAge(int age) { this.age = age; }
    }
}

PUT/PATCH/DELETE操作

import io.restassured.http.ContentType;
import org.testng.annotations.Test;
public class UpdateDeleteTests {
    @Test
    public void testUpdateUser() {
        String updateBody = """
            {
                "name": "Updated Name",
                "email": "updated@example.com"
            }
            """;
        given()
            .contentType(ContentType.JSON)
            .body(updateBody)
        .when()
            .put("/users/1")
        .then()
            .statusCode(200)
            .body("name", equalTo("Updated Name"));
    }
    @Test
    public void testPartialUpdateUser() {
        String patchBody = """
            {
                "age": 30
            }
            """;
        given()
            .contentType(ContentType.JSON)
            .body(patchBody)
        .when()
            .patch("/users/1")
        .then()
            .statusCode(200)
            .body("age", equalTo(30));
    }
    @Test
    public void testDeleteUser() {
        given()
            .pathParam("id", 1)
        .when()
            .delete("/users/{id}")
        .then()
            .statusCode(204); // 204 No Content
    }
}

高级响应验证

import io.restassured.response.Response;
import org.testng.annotations.Test;
import java.util.List;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ResponseValidationTests {
    @Test
    public void testResponseHeaders() {
        given()
        .when()
            .get("/users/1")
        .then()
            .statusCode(200)
            .header("Content-Type", containsString("application/json"))
            .header("Server", equalTo("nginx"))
            .time(lessThan(2000L)); // 响应时间小于2秒
    }
    @Test
    public void testComplexNestedJson() {
        Response response = given()
            .when()
            .get("/users/1/posts")
            .then()
            .statusCode(200)
            .extract()
            .response();
        // 提取数据
        String userName = response.jsonPath().getString("author.name");
        List<String> titles = response.jsonPath().getList("posts.title");
        int postCount = response.jsonPath().getInt("posts.size()");
        // 验证嵌套结构
        given()
        .when()
            .get("/users/1/posts")
        .then()
            .body("author.name", equalTo("John Doe"))
            .body("posts[0].title", containsString("First"))
            .body("posts.findAll { it.likes > 100 }.size()", greaterThan(0));
    }
    @Test
    public void testMultipleAssertions() {
        given()
        .when()
            .get("/users")
        .then()
            .statusCode(200)
            .assertThat()
            .body("data.name", hasItems("Alice", "Bob"))
            .body("data.findAll { it.age > 25 }.age", everyItem(greaterThan(25)))
            .body("total_pages", allOf(greaterThan(0), lessThan(10)));
    }
    @Test
    public void testXmlResponse() {
        given()
            .accept("application/xml")
        .when()
            .get("/users/1")
        .then()
            .statusCode(200)
            .body("user.name", equalTo("John Doe"))
            .body("user.address.city", equalTo("New York"));
    }
}

认证和Token处理

import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.*;
public class AuthTests {
    private static String authToken;
    @BeforeClass
    public void setup() {
        // 获取认证Token
        String loginBody = """
            {
                "username": "testuser",
                "password": "testpass"
            }
            """;
        authToken = given()
            .contentType(ContentType.JSON)
            .body(loginBody)
        .when()
            .post("/auth/login")
        .then()
            .statusCode(200)
            .extract()
            .path("token");
    }
    @Test
    public void testWithBearerToken() {
        given()
            .header("Authorization", "Bearer " + authToken)
        .when()
            .get("/protected/resource")
        .then()
            .statusCode(200);
    }
    @Test
    public void testWithBasicAuth() {
        given()
            .auth()
            .basic("username", "password")
        .when()
            .get("/basic-auth-endpoint")
        .then()
            .statusCode(200);
    }
    @Test
    public void testWithOAuth2() {
        // 简化示例,实际需要更复杂的OAuth2流程
        given()
            .auth()
            .oauth2(authToken)
        .when()
            .get("/oauth2/endpoint")
        .then()
            .statusCode(200);
    }
}

完整测试框架示例

import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class CompleteTestFramework {
    private static RequestSpecification requestSpec;
    private static ResponseSpecification responseSpec;
    @BeforeClass
    public void setup() {
        // 配置请求规范
        requestSpec = new RequestSpecBuilder()
            .setBaseUri("https://api.example.com")
            .setContentType(ContentType.JSON)
            .addHeader("X-API-Key", "your-api-key")
            .build();
        // 配置响应规范
        responseSpec = new ResponseSpecBuilder()
            .expectStatusCode(200)
            .expectContentType(ContentType.JSON)
            .expectResponseTime(lessThan(3000L))
            .build();
        // 全局设置
        RestAssured.requestSpecification = requestSpec;
        RestAssured.responseSpecification = responseSpec;
    }
    @Test
    public void completeUserFlow() {
        // 1. 创建用户
        String userId = given()
            .body("""
                {
                    "name": "Test User",
                    "email": "test@example.com",
                    "password": "password123"
                }
                """)
        .when()
            .post("/users")
        .then()
            .statusCode(201)
            .extract()
            .path("id");
        // 2. 获取用户信息
        given()
            .pathParam("id", userId)
        .when()
            .get("/users/{id}")
        .then()
            .spec(responseSpec)
            .body("id", equalTo(userId))
            .body("name", equalTo("Test User"));
        // 3. 更新用户信息
        given()
            .pathParam("id", userId)
            .body("""
                {
                    "name": "Updated Name"
                }
                """)
        .when()
            .patch("/users/{id}")
        .then()
            .statusCode(200)
            .body("name", equalTo("Updated Name"));
        // 4. 删除用户
        given()
            .pathParam("id", userId)
        .when()
            .delete("/users/{id}")
        .then()
            .statusCode(204);
    }
}

文件上传和下载

import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import java.io.File;
public class FileHandlingTests {
    @Test
    public void testFileUpload() {
        given()
            .multiPart("file", new File("/path/to/file.pdf"))
            .multiPart("description", "Test document")
        .when()
            .post("/upload")
        .then()
            .statusCode(200)
            .body("success", equalTo(true));
    }
    @Test
    public void testFileDownload() {
        byte[] fileContent = given()
            .when()
            .get("/download/report.pdf")
        .then()
            .statusCode(200)
            .extract()
            .asByteArray();
        // 保存到文件
        try {
            java.nio.file.Files.write(
                java.nio.file.Paths.get("report.pdf"), 
                fileContent
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Test
    public void testUploadMultipleFiles() {
        given()
            .multiPart("files[]", new File("/path/to/file1.txt"))
            .multiPart("files[]", new File("/path/to/file2.txt"))
            .multiPart("metadata", """
                {
                    "category": "documents",
                    "description": "Test files"
                }
                """)
        .when()
            .post("/multi-upload")
        .then()
            .statusCode(200)
            .body("uploaded_count", equalTo(2));
    }
}

日志和调试

import org.testng.annotations.Test;
public class LoggingTests {
    @Test
    public void testWithLogging() {
        given()
            .log().all() // 记录所有请求信息
        .when()
            .get("/users/1")
        .then()
            .log().all() // 记录所有响应信息
            .statusCode(200);
    }
    @Test
    public void testSelectiveLogging() {
        given()
            .log().method()
            .log().uri()
            .log().headers()
            .log().body()
        .when()
            .get("/users/1")
        .then()
            .log().status()
            .log().headers()
            .statusCode(200);
    }
    @Test
    public void testLogOnFailure() {
        given()
            .when()
            .get("/invalid-endpoint")
        .then()
            .log().ifValidationFails() // 只在失败时记录
            .statusCode(404);
    }
}

并行测试和性能优化

import org.testng.annotations.Test;
import java.util.concurrent.CompletableFuture;
public class ParallelTests {
    @Test
    public void testParallelRequests() {
        // 并发请求示例
        CompletableFuture.allOf(
            CompletableFuture.runAsync(() -> {
                given().when().get("/users/1").then().statusCode(200);
            }),
            CompletableFuture.runAsync(() -> {
                given().when().get("/users/2").then().statusCode(200);
            }),
            CompletableFuture.runAsync(() -> {
                given().when().get("/users/3").then().statusCode(200);
            })
        ).join();
    }
    @Test(invocationCount = 5, threadPoolSize = 5)
    public void testRepeatedRequests() {
        given()
        .when()
            .get("/test-endpoint")
        .then()
            .statusCode(200);
    }
}

数据驱动测试

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DataDrivenTests {
    @DataProvider(name = "userData")
    public Object[][] userData() {
        return new Object[][] {
            {"Alice", 25, true},
            {"Bob", 30, true},
            {"Charlie", 17, false}, // 未成年人
            {"David", 35, true}
        };
    }
    @Test(dataProvider = "userData")
    public void testUserValidation(String name, int age, boolean expectedValid) {
        String userBody = String.format(
            "{\"name\":\"%s\",\"age\":%d}", name, age
        );
        given()
            .contentType(ContentType.JSON)
            .body(userBody)
        .when()
            .post("/validate-user")
        .then()
            .statusCode(200)
            .body("valid", equalTo(expectedValid));
    }
    @DataProvider(name = "postsData")
    public Object[][] postsData() {
        return new Object[][] {
            {1, "Post 1"},
            {2, "Post 2"},
            {3, "Post 3"}
        };
    }
    @Test(dataProvider = "postsData")
    public void testMultiplePosts(int postId, String expectedTitle) {
        given()
            .pathParam("id", postId)
        .when()
            .get("/posts/{id}")
        .then()
            .statusCode(200)
            .body("title", equalTo(expectedTitle));
    }
}

这些示例涵盖了REST Assured的主要功能,要运行这些测试,您需要:

  1. 在pom.xml中添加依赖:

    <dependencies>
     <!-- REST Assured -->
     <dependency>
         <groupId>io.rest-assured</groupId>
         <artifactId>rest-assured</artifactId>
         <version>5.4.0</version>
         <scope>test</scope>
     </dependency>
     <!-- TestNG -->
     <dependency>
         <groupId>org.testng</groupId>
         <artifactId>testng</artifactId>
         <version>7.8.0</version>
         <scope>test</scope>
     </dependency>
     <!-- JSON 解析 -->
     <dependency>
         <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-databind</artifactId>
         <version>2.16.1</version>
     </dependency>
    </dependencies>

这些案例涵盖了REST API测试的常见场景,您可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!