Не удалось выполнить запрос POST (тест с подтверждением)

У меня проблема с получением запроса POST с гарантированным отдыхом.

Этот код работает:

given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").    
        when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal)); 

Но я пытался использовать методы param() или parameter():

Это дает:

given().parameter("key", "val").                                      
        when().post(url + resource).then().assertThat().statusCode(200);  

Expected status code <200> doesn't match actual status code <415>.

Это:

    given().parameter("key", "val").                                                         
            when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));  

java.lang.IllegalStateException: Expected response body to be verified as JSON, HTML or XML but no content-type was defined in the response. Try registering a default parser using: RestAssured.defaultParser(<parser type>);

И это:

RestAssured.defaultParser = Parser.JSON;                                                   
given().parameter("key", "val").                                                       
        when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));

java.lang.IllegalArgumentException: The JSON input text should neither be null nor empty

У меня закончились идеи, что не так.

То, что я пытаюсь сделать, - это не писать полные jsons для всех тестов, это будет быстрее, если я могу пропустить все "" и {}. Правильно ли мой подход?

Ответ 1

Посмотрите на свой первый пример:

given().contentType(ContentType.JSON).body("{\"key\": \"val\"}").    
        when().post(url + resource).then().assertThat().statusCode(200).body("otherVal", equalTo(otherVal));

Что происходит, так это то, что вы помещаете { "key" : "val" } (как текст) в тело запроса. Этот текст - это JSON. В REST Assured view вы также могли бы поставить { "key" : "val", который недействителен JSON. Ваш сервер отвечает правильно, так как сервер требует и понимает JSON. Он понимает, что тело должно быть JSON, поскольку вы передаете JSON как контент-тип.

Итак, давайте посмотрим на ваш второй пример:

given().parameter("key", "val").                                      
        when().post(url + resource).then().assertThat().statusCode(200);

Здесь ваш сервис возвращает 415, потому что вам не хватает содержимого контента JSON. Что происходит, когда вы используете param или parameter с POST, это то, что вы создаете параметры формы. Параметры формы также отправляются в тело запроса, но параметры формы не являются JSON! Указание "ключ" и "val" в качестве параметра формы, как вы, будет таким же:

given().contentType("x-www-form-urlencoded").body("key=val").when().url + resource).then().assertThat().statusCode(200);

Итак, в вашем втором примере есть две проблемы:

  • Вы не отправляете JSON
  • У вас неправильный тип содержимого

И из-за (2) вы получаете 415 с сервера

Перейдем к вашему третьему примеру:

given().parameter("key", "val").                                                         
            when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));

Что (возможно) происходит здесь, так это то, что ваш сервер не содержит тело ответа, потому что он ожидает, что запрос будет включать "application/json" в качестве типа контента. Так что нет тела для утверждения (просьба неверна)! Ответ содержит только статус 415 (строка) в качестве заголовка.

Что приводит нас к вашему последнему примеру:

RestAssured.defaultParser = Parser.JSON;                                                   
given().parameter("key", "val").                                                       
        when().post(url + resource).then().assertThat().body("otherVal", equalTo(otherVal));

Здесь вы инструктируете REST Assured обрабатывать отсутствующий тип содержимого как JSON, но проблема (опять же) заключается в том, что ваш сервер вообще не возвращает тело ответа, так что это не поможет.

Решение:

В свой путь к классам (например, jackson-databind) вы должны поместить поддерживаемую инфраструктуру объектно-ориентированного JSON (Jackson, Faster Jackson, Simple JSON или Gson) и просто создать карту, как описано в документация:

Map<String, Object>  jsonAsMap = new HashMap<>();
map.put("key", "val");

given().
        contentType(ContentType.JSON).
        body(jsonAsMap).
when().
        post(url + resource).
then().
        statusCode(200).
        body("otherVal", equalTo(otherVal)); 

Так как создание карт в Java довольно многословно, я обычно делаю что-то вроде этого, если у меня есть вложенные карты:

given().
        contentType(ContentType.JSON).
        body(new HashMap<String,Object>() {{
             put("key1, "val1");
             put("key2, "val2");
             put("key3", asList("val3", "val4"));
             put("nested", new HashMap<String,String>() {{
                 put("key4", "val4");
                 put("key5", "val5");
             }});
        }}).
when().
        post(url + resource).
then().
        statusCode(200).
        body("otherVal", equalTo(otherVal)); 

Или вы создаете представление DTO своих данных и просто передаете объект в REST Assured:

MyDTO myDTO = new MyDTO(...);
given().
        contentType(ContentType.JSON).
        body(myDTO).
when().
        post(url + resource).
then().
        statusCode(200).
        body("otherVal", equalTo(otherVal)); 

Вы можете прочитать больше в документации по сопоставлению объектов.

Ответ 2

Я искал ответ, и я тоже понял это.

добавьте файл в папку src/test/resouces и добавьте этот код в свой тест. Должно быть все хорошо

URL file = Resources.getResource("ModyNewFieldsReq.json");
String myRequest = Resources.toString(file,Charsets.UTF_8);

Response fieldResponse =  given ()
       .header("Authorization", AuthrztionValue)
       .header("X-App-Client-Id", XappClintIDvalue)
       .contentType("application/vnd.api+json")
       .body(myRequest).with()

     .when()
       .post(dataPostUrl)    

    .then()
       .assertThat()
       .log().ifError()
       .statusCode(200)
       .extract().response();

Assert.assertFalse(fieldResponse.asString().contains("isError"));