Monday, April 11, 2016

Using REST Assured



https://github.com/rest-assured/rest-assured/wiki/Usage
https://github.com/rest-assured/rest-assured/blob/master/examples/rest-assured-itest-java/src/test/java/io/restassured/itest/java/AuthenticationITest.java
given().auth().basic("jetty", "jetty").expect().statusCode(200).when().get("/secured/hello");
RestAssured.reset();

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.2</version>
</dependency>
http://stackoverflow.com/questions/15531767/rest-assured-generic-list-deserialization
UPDATE: Using Rest-Assured 1.8.1, looks like cast to List is not supported anymore. You need to declare and object array like this:
Person[] persons = given().when().get("person/").as(Person[].class);

You could also do this if you were interested in using "expect()"
expect().
 body("get(0).firstName", equalTo("Mike")).
when().
 get("person/");
List<Artwork> returnedArtworks = Arrays.asList(response.getBody().as(Artwork[].class));
http://blog.philipphauer.de/testing-restful-services-java-best-practices

Use Reusable RequestSpecifications

Create a RequestSpecification to reuse request configurations (base URL, parameters, content type, debugging logging) that you want to use for all requests.
private static RequestSpecification spec;
@BeforeClass
public static void initSpec(){
    spec = new RequestSpecBuilder()
            .setContentType(ContentType.JSON)
            .setBaseUri("http://localhost:8080/")
            .addFilter(new ResponseLoggingFilter())//log request and response for better debugging. You can also only log if a requests fails.
            .addFilter(new RequestLoggingFilter())
            .build();
}

//nice reusable method
private String createResource(String path, Object bodyPayload) {
    return given()
            .spec(spec)
            .body(bodyPayload)
            .when()
            .post(path)
            .then()
            .statusCode(201)
            .extract().header("location");
}
//nice reusable method
private <T> T getResource(String locationHeader, Class<T> responseClass) {
    return given()
                .spec(spec)
                .when()
                .get(locationHeader)
                .then()
                .statusCode(200)
                .extract().as(responseClass);

}
https://groups.google.com/forum/#!topic/rest-assured/E2f8K2gYAck
static final Matcher<Integer> SUCCESS = isOneOf(201, 202, 204);
I usually just do statusCode(and(greaterThanOrEqualTo(200), lessThan(300)).
http://stackoverflow.com/questions/27236917/rest-assured-sprint-security-login
You don't need to go to the login page to login, REST Assured does this automatically. This works:
RestAssured.baseURI = "http://myapp-breakid.rhcloud.com";
RestAssured.authentication = form("admin", "sababa1.", springSecurity());

get("/index").prettyPrint();
What happens here is that form authentication is automatically performed before each request. If it's important to use the same session in multiple requests you should use a session filter. For example:
RestAssured.baseURI = "http://myapp-breakid.rhcloud.com";

SessionFilter sessionFilter = new SessionFilter();

given().
        auth().form("admin", "sababa1.", springSecurity()).
        filter(sessionFilter).
when().
        get("/index");

// Session filter will automatically capture the session id and you can reuse it in subsequent requests.

given().
        filter(sessionFilter).
when().
        get("/another_protected_resource").
then().
        statusCode(200);
You can also get the sessionId from the SessionFilter and use it like this:
given().
        sessionId(sessionFilter.getSessionId()).
when().
        get("/another_protected_resource").
then().
        statusCode(200);

RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();

import static com.jayway.restassured.RestAssured.given;
http://allegro.tech/2014/11/testing-restful-service-and-clients.html
@Before
public void setUp() {
    // set default port for REST-assured
    RestAssured.port = 80;

    // set default URI for REST-assured.
    // In integration tests, this would most likely point to localhost.
    RestAssured.baseURI = "http://api.openweathermap.org";
}
http://james-willett.com/2015/06/extracting-a-json-response-with-rest-assured/
https://angeltechltd.wordpress.com/2014/10/19/rest-assured-validating-json/

https://github.com/jayway/rest-assured/wiki/Usage
given().
        config(newConfig().jsonConfig(jsonConfig().numberReturnType(BIG_DECIMAL))).
when().
        get("/price").
then().
        body("price", is(new BigDecimal(12.12));

http://testdetective.com/rest-assured-going-deeper/
Sending request’s body as string is easy and straightforward, but it can be inconvenient in the case of more complex operations on request / response properties. Proven solution for this is a good-known serialization of request/response body to objects. REST-Assured supports object mapping to (and from) JSON and XML. For JSON you need either to have Jackson or Gson in your classpath and for XML you need JAXB

  JSON Schema Validation Main idea behind JSON Schema Validation is to compare response correctness with declared schema
Second, declare schema definition in json file. Below you can see simple example for checking presence of response properties and types:
given().
    contentType("application/json").
when().
    get("/user/" + userId).
then().
    body(matchesJsonSchemaInClasspath("test-schema.json"));
After calling /user/{id} method, REST-Assured invokes json schema’s matchesJsonSchemaInClasspath() method, witch compares response against schema definition previously declared in project.

when()
  .get("/products")
.then()
  .body("music.albums.findAll { it.price > 18 }.album", hasItems("Sabbath Bloody Sabbath"));  
http://testdetective.com/rest-assured-framework-overview/
One of my favourite is log method. Below is an example of using built-in logger in rest-assured method.
when().get("/ping").
then().
    log().all().
    body(containsString("pong!"));

Another important feature is HTTPS Validation. If you have some HTTPS issues, and your test flow doesn’t check any security cases, you can simply call:
RestAssured.useRelaxedHTTPSValidation();
One of the most obvious use case would be extracting values.
Response response =
    given().log().all().
        contentType("application/json").
    when().
        get("/user/" + userId).
    then().
        statusCode(200).
    extract().response();  

JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV4).freeze()).freeze();
// When
get("/products").then().assertThat().body(matchesJsonSchemaInClasspath("products-schema.json").using(jsonSchemaFactory));

Anonymous JSON root validation
A JSON document doesn't necessarily need a named root attribute. This is for example valid JSON:
[1, 2, 3]
An anonymous JSON root can be verified by using $ or an empty string as path

when().
     get("/json").
then().
     body("$", hasItems(1, 2, 3)); // An empty string "" would work as well
with().parameters("firstName", "John", "lastName", "Doe").when().post("/greetXML").then().body("greeting.firstName", equalTo("John"), "greeting.lastName", equalTo("Doe"));

Getting Response Data
InputStream stream = get("/lotto").asInputStream(); // Don't forget to close this one when you're done
byte[] byteArray = get("/lotto").asByteArray();
String json = get("/lotto").asString();

String nextTitleLink =
given().
        param("param_name", "param_value").
when().
        get("/title").
then().
        contentType(JSON).
        body("title", equalTo("My Title")).
extract().
        path("_links.next.href");
get(nextTitleLink). ..

Response response =
given().
        param("param_name", "param_value").
when().
        get("/title").
then().
        contentType(JSON).
        body("title", equalTo("My Title")).
extract().
        response();
String nextTitleLink = response.path("_links.next.href");
String headerValue = response.header("headerName");

Once we have the response body we can then use the JsonPath to get data from the response body:

int lottoId = from(json).getInt("lotto.lottoId");
List<Integer> winnerIds = from(json).get("lotto.winners.winnerId");
Or a bit more efficiently:

JsonPath jsonPath = new JsonPath(json).setRoot("lotto");
int lottoId = jsonPath.getInt("lottoId");
List<Integer> winnerIds = jsonPath.get("winners.winnderId");


Multi-value parameter
given().param("myList", "value1", "value2"). ..
or using a list:

List<String> values = new ArrayList<String>();
values.add("value1");
values.add("value2");

given().param("myList", values). ..
Path parameters

You can also specify so called path parameters in your request, e.g.

post("/reserve/{hotelId}/{roomNumber}", "My Hotel", 23);
These kinds of path parameters are referred to "unnamed path parameters" in REST Assured since they are index based (hotelId will be equal to "My Hotel" since it's the first placeholder).

You can also use named path parameters:

given().
        pathParam("hotelId", "My Hotel").
        pathParam("roomNumber", 23).
when().
        post("/reserve/{hotelId}/{roomNumber}").

given().
        pathParam("hotelId", "My Hotel").      
when().
        post("/reserve/{hotelId}/{roomNumber}", 23).

Use the response to verify other parts of the response
{ "userId" : "some-id", "href" : "http://localhost:8080/some-id" }
get("/x").then().body("href", response -> equalTo("http://localhost:8080/" + response.path("userId"));
get("/x").then().body("href", endsWithPath("userId"));

get("/x").then().body("href", and(startsWith("http:/localhost:8080/"), endsWithPath("userId")));

Measuring Response Time
when().
      get("/lotto").
then().
      time(lessThan(2000L)); // Milliseconds
Authentication
given().auth().basic("username", "password"). ..
but you can also define authentication for all requests:

RestAssured.authentication = basic("username", "password");

Preemptive Basic Authentication

This will send the basic authentication credential even before the server gives an unauthorized response in certain situations, thus reducing the overhead of making an additional connection. This is typically what you want to use in most situations unless you're testing the servers ability to challenge. Example:

given().auth().preemptive().basic("username", "password").when().get("/secured/hello").then().statusCode(200);

Form Authentication
given().
        auth().form("John", "Doe", FormAuthConfig.springSecurity()).
when().
        get("/formAuth");
then().
        statusCode(200);

given().
        auth().form("John", "Doe", new FormAuthConfig("/j_spring_security_check", "j_username", "j_password")).
when().
        get("/formAuth");
then().
        statusCode(200);      
CSRF
Today it's common for the server to supply a CSRF token with the response in order to avoid these kinds of attacks. REST Assured has support for automatically parsing and supplying the CSRF token to the server. In order for this to work REST Assured must make an additional request and parse (parts) of the website.

You can enable CSRF support by doing the following:

given().
        auth().form("John", "Doe", formAuthConfig().withAutoDetectionOfCsrf()).
when().
        get("/formAuth");
then().
        statusCode(200);
Now REST Assured will automatically try to detect if the webpage contains a CSRF token. In order to assist REST Assured and make the parsing more robust it's possible to supply the CSRF field name (here we imagine that we're using Spring Security default values and thus can make use of the predefined springSecurity FormAuthConfig):

given().
        auth().form("John", "Doe", springSecurity().withCsrfFieldName("_csrf")).
when().
        get("/formAuth");
then().
        statusCode(200);
We've now told REST Assured to search for the CSRF field name called "_csrf" (which is it both faster and less prone to error).

By default the CSRF value is sent as a form parameter with the request but you can configure to send it as a header instead if that's required:

given().
        auth().form("John", "Doe", springSecurity().withCsrfFieldName("_csrf").sendCsrfTokenAsHeader()).
when().
        get("/formAuth");
then().
        statusCode(200);
given().multiPart("controlName", new File("/path/to/file")).when().post("/upload");

It's also possible to supply multiple "multi-parts" entities in the same request:

byte[] someData = ..
given().
        multiPart("controlName1", new File("/path/to/file")).
        multiPart("controlName2", "my_file_name.txt", someData).
        multiPart("controlName3", someJavaObject, "application/json").
when().post("/upload");

Message message = get("/message").as(Message.class);
Message message = get("/message").as(Message.class, ObjectMapperType.GSON);
RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig(myObjectMapper));

Response Logging
get("/x").then().log().body() ..
get("/x").then().log().all(). ..
get("/x").then().log().ifStatusCodeIsEqualTo(302). .. // Only log if the status code is equal to 302
get("/x").then().log().ifStatusCodeMatches(matcher). .. // Only log if the status code matches the supplied Hamcrest matcher

given().log().ifValidationFails(). ..
To log the response do:

.. .then().log().ifValidationFails(). ..
given().config(RestAssured.config().logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails(HEADERS))). ..

Session Filter
SessionFilter sessionFilter = new SessionFilter();

given().auth().form("John", "Doe").filter(sessionFilter).when().get("/formAuth").then().statusCode(200);

given().filter(sessionFilter). // Reuse the same session filter instance to automatically apply the session id from the previous response
when().get("/x").then().statusCode(200);

RestAssured.useRelaxedHTTPSValidation();
SSL invalid hostname
RestAssured.config = RestAssured.config().sslConfig(sslConfig().allowAllHostnames());
http://www.jayway.com/2013/04/12/whats-new-in-rest-assured-1-8/
https://github.com/jayway/JsonPath

https://github.com/jayway/rest-assured
get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));
Get and verify all winner ids:
get("/lotto").then().assertThat().body("lotto.winners.winnerId", hasItems(23, 54));
     RestAssured.baseURI  = "http://127.0.0.1:5984/restassured"; 

     Response r = given()
     .contentType("application/json").
     body("{\"name\":\"Jimi Hendrix\"}").
        when().
        post("");

     String body = r.getBody().asString();

final Response response = given().headers(headers).filter(sessionFilter).
when().get(requestUrl).then().statusCode(isOneOf(200, 202, 204)).extract().response();

Response response =
given().contentType(ContentType.URLENC).header(originHeader).formParameters(parameters).when()
.post(url).then().extract().response();

return response.getBody().jsonPath().get("field_name");  
post(requestURL).then().extract().response().path("id")

http://unirest.io/java.html

HttpResponse<JsonNode> response = Unirest.get("http://httpbin.org/headers").basicAuth("username", "password").asJson();
HttpResponse<JsonNode> jsonResponse = Unirest.post("http://httpbin.org/post")
  .header("accept", "application/json")
  .body("{\"parameter\":\"value\", \"foo\":\"bar\"}")
  .asJson();
HttpResponse<JsonNode> jsonResponse = Unirest.post("http://httpbin.org/post")
  .header("accept", "application/json")
  .field("parameter", "value")
  .field("file", new File("/tmp/file"))

  .asJson();  

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts