Ohhnews

分类导航

$ cd ..
DZone Java原文

如何使用 REST-Assured Java 进行 PUT API 接口测试

#接口测试#自动化测试#rest-assured#java#api 开发

PUT 请求通常用于更新现有资源。这意味着使用 API 请求正文中发送的数据来替换目标资源的当前数据。与 POST 请求一样,Content-Type 标头非常重要,因为它告诉服务器如何解析我们发送的数据。

当请求成功时,PUT 请求通常会返回 200 OK 状态码,并在响应中包含更新后的资源。话虽如此,并非所有 API 的行为方式都相同;根据 API 的设计,有些 API 可能选择完全不返回任何数据。

PUT 与 POST API 的区别

下表清晰地展示了 PUT 和 POST API 之间的区别:

标准PUTPOST
用途用于完全更新或替换现有资源。用于创建新资源或向资源提交数据。
幂等性幂等;多次执行相同的请求会产生相同的结果。非幂等;多次执行相同的请求可能会创建多条记录。
响应状态码通常返回 200 OK 并附带更新后的资源。通常返回 201 Created 并附带新资源详情。
使用场景示例更新用户的个人资料信息。创建一个新的用户账户。

PUT API 示例

让我们以 PUT /updateOrder/{id} API 为例,它使用订单 ID 来更新现有的订单。该 API 是 GitHub 上 RESTful 电子商务 应用程序的一部分。

[LOADING...]

此 API 需要一个身份验证令牌来识别并更新订单。如果令牌缺失或无效,请求将报错失败。order ID 必须作为路径参数提供,以便识别并更新相应的订单。更新后的订单详情必须以 JSON 格式包含在请求正文中。需要注意的是,由于这是一个 PUT 请求,我们必须发送整个订单对象,而不仅仅是我们要更改的字段。即使我们只更新单个值,也必须提供完整的订单数据。

我们将使用以下测试场景来演示如何使用 REST-assured Java 测试 PUT API。

## 测试场景
标题:更新系统中的现有订单。
前置条件:系统中存在有效的订单。

## 测试步骤
1. 更新订单 ID 为 "2" 的所有订单详情。
2. 验证响应返回的状态码为 200。
3. 断言订单详情已正确更新。

测试实现

此测试场景的实现分为两个部分:

  1. 编写一个测试来调用授权 API 并从中提取令牌。(因为更新订单必须使用授权令牌)。
  2. 更新订单并验证更新后的详情。

第 1 步:编写测试以生成并提取令牌

POST /auth API 将用户名和密码作为请求正文,并在响应中返回授权令牌,状态码为 201。

[LOADING...]

让我们创建一个名为 TestPutRequestExamples 的新 Java 类来实现此测试场景,并在其中创建一个新方法 testTokenGeneration()

$ java
public class TestPutRequestExamples {
    private String token;

    @Test
    public void testTokenGeneration () {
        String requestBody = """
            {
                "username": "admin",
                "password": "secretPass123"
            }""";
        token = given ().contentType (ContentType.JSON)
                .when ()
                .body (requestBody)
                .post ("http://localhost:3004/auth")
                .then ()
                .statusCode (201)
                .and ()
                .body ("token", notNullValue ())
                .extract ()
                .path ("token");
    }
}

testTokenGeneration() 测试使用 REST-assured 发送包含登录凭据的 POST 请求以生成身份验证令牌。它验证响应是否返回 201 状态码并确保令牌存在。最后,它提取并存储授权令牌到全局级别的 "token" 变量中,以便其他测试可以使用该值。

第 2 步:使用 PUT 请求更新订单

让我们在同一个类中创建一个新的测试方法 testUpdateOrder()。此测试将使用通过 Builder 模式 + Datafaker 库 生成的 OrderData,这样我们就不必担心手动更新测试数据。

订单对象的 POJO:

$ java
@Getter
@Setter
@Builder
@JsonPropertyOrder ({ "user_id", "product_id", "product_name", "product_amount", "qty", "tax_amt", "total_amt" })
public class OrderData {
    @JsonProperty ("user_id")
    private String userId;
    @JsonProperty ("product_id")
    private String productId;
    @JsonProperty ("product_name")
    private String productName;
    @JsonProperty ("product_amount")
    private int productAmount;
    private int qty;
    @JsonProperty ("tax_amt")
    private int taxAmt;
    @JsonProperty ("total_amt")
    private int totalAmt;
}

OrderData 类是一个用于表示订单详情的 POJO,其中来自 Lombok 的 @Getter@Setter@Builder 注解减少了样板代码。Jackson 注解 @JsonProperty@JsonPropertyOrder 确保在发送或接收 API 请求时进行正确的 JSON 字段映射和排序。

使用 Datafaker 库生成带有随机值的新订单:

$ java
public class OrderDataBuilder {
    public static OrderData getOrderData () {
        Faker faker = new Faker ();
        int productAmount = (faker.number () .numberBetween (1, 1999));
        int qty = faker.number () .numberBetween (1, 10);
        int grossAmt = qty * productAmount;
        int taxAmt = (int) (grossAmt * 0.10);
        int totalAmt = grossAmt + taxAmt;

        return OrderData.builder ()
                .userId (String.valueOf (faker.number () .numberBetween (301, 499)))
                .productId (String.valueOf (faker.number () .numberBetween (201, 533)))
                .productName (faker.commerce () .productName ())
                .productAmount (productAmount)
                .qty (qty)
                .taxAmt (taxAmt)
                .totalAmt (totalAmt)
                .build ();
    }
}

第 3 步:编写测试以更新并验证订单

让我们在现有的 TestPutRequestExamples 类中创建一个新的测试方法 testUpdateOrder()

$ java
@Test
public void testUpdateOrder () {
    int orderId = 1;
    OrderData updatedOrder = getOrderData ();
    String responseBody = given ().contentType (ContentType.JSON)
            .header ("Authorization", token)
            .when ()
            .log () .all ()
            .body (updatedOrder)
            .put ("http://localhost:3004/updateOrder/" + orderId)
            .then ()
            .log () .all ()
            .statusCode (200)
            .and ()
            .assertThat ()
            .body ("message", equalTo ("Order updated successfully!"))
            .extract ()
            .response ()
            .asPrettyString ();

    JSONObject responseObject = new JSONObject (responseBody);
    JSONObject orderObject = responseObject.getJSONObject ("order");

    assertThat (orderObject.get ("id"), equalTo (orderId));
    assertThat (orderObject.get ("user_id"), equalTo (updatedOrder.getUserId ()));
    assertThat (orderObject.get ("product_id"), equalTo (updatedOrder.getProductId ()));
    assertThat (orderObject.get ("product_name"), equalTo (updatedOrder.getProductName ()));
    assertThat (orderObject.get ("product_amount"), equalTo (updatedOrder.getProductAmount ()));
    assertThat (orderObject.get ("qty"), equalTo (updatedOrder.getQty ()));
    assertThat (orderObject.get ("tax_amt"), equalTo (updatedOrder.getTaxAmt ()));
    assertThat (orderObject.get ("total_amt"), equalTo (updatedOrder.getTotalAmt ()));
}

testUpdateOrder() 方法发送带有授权和 JSON 正文的 PUT 请求,验证响应状态,并确保更新后的订单数据与请求负载匹配。

[LOADING...]

代码可以分为以下几类以便于理解:

  • 请求构建方法
    • given():开始构建 API 请求的入口点。
    • .contentType(ContentType.JSON):指定请求正文为 JSON 格式。
    • .header("Authorization", token):添加 Authorization 标头并使用全局变量 token 进行身份验证。
  • 请求执行方法
    • when():标记从请求设置到执行的转换。
    • .log().all():记录完整的请求详情,有助于简化调试过程。
    • .body(updatedOrder):将 updatedOrder 对象作为请求负载发送,并自动将 Java 对象转换为 JSON。
    • .put(...):发送 PUT 请求以更新现有订单。
  • 响应验证方法
    • then():开始响应验证。
    • .statusCode(200):验证请求已成功执行且返回了 200 OK 状态。
  • 响应正文提取
    • .extract().response().asString():提取响应并将其转换为可读的 JSON 字符串。

测试执行

测试应以特定顺序执行,即先运行令牌生成测试,再运行更新订单测试。我们可以创建一个 testng.xml 文件来按顺序运行测试。

[LOADING...]

总结

测试 PUT 请求在自动化测试中非常重要,因为它们通常用于更新或修改现有数据。使用 Datafaker 有助于生成随机测试数据,从而实现对 PUT 端点的有效测试,同时避免重复数据问题。在自动化 PUT 请求时,提供正确的标头并确保数据以预期的格式发送至关重要。如果 API 需要授权令牌,也应将其包含在内。此外,使用 testng.xml 是在本地或 CI/CD 流水线中顺序运行 API 自动化测试的推荐方式。在我的经验中,覆盖自动化测试中的“快乐路径”和负面场景有助于保持回归测试套件的高效性,并使发现问题变得更容易。使用基于 POJO 的方法有助于轻松创建、管理和维护请求与响应负载,使测试代码更具可读性和可维护性。祝测试愉快!