Pawel Veselov
Pawel Veselov

Reputation: 4225

How to extract cookies from a REST Assured response using common code

Using REST Assured (4.3.3, from Java) I can freely manipulate request and response specification objects in a base test class, so that when the actual test needs a request specification to execute the actual call, it's "pre-configured" with certain common statements. For example:

public abstract class TestBase
    protected RequestSpecification request() {
        return given()
                .cookies(globalCookies)
                .port(serverPort)
                .log().ifValidationFails()
                .then()
                .log().ifValidationFails()
                .given();
    }
}
public class ActualTest extends TestBase {
  @Test
  public void test1() {
    String content = request().get("/some").then()
           .statusCode(200)
           .extract()
           .body().asString();
  }
}

What I'd like to do now is to "pre-configure" the specifications to preserve cookies between the requests. I am feeding the list of cookies to send using RequestSpecification.cookies(Cookies), but I can't find any way to instruct the specifications to extract the returned cookies before obtaining the instance of Response. However, such instance is only available after calling one of the RequestSender methods, which I can't do in the base code.

The methods I've considered to solve this are outlined below, but the first two are quite clunky, and the third is probably just outright wrong as it meddles with classes in "internal" sub-packages. Is there a "right" way of doing this?

  1. Add a base method saveCookies() that takes in an instance of ValidatableResponse, on which it can call extract(), and get the cookies. Then each test will have to use the method.
public abstract class TestBase
  // ...
  protected ValidatableResponse saveCookies(ValidatableResponse r) {
    saveGlobalCookies(r.extract().detailedCookies());
    return r;
  }
}
public class ActualTest extends TestBase {
  @Test
  public void test1() {
    String content = saveCookies(request().get("/some").then())
           .statusCode(200)
           .extract()
           .body().asString();
  }
}
  1. Use a base method that takes in lambdas so that the potentially intermediate ValidatableResponse can be intercepted, and the final result (if needed) returned to the invoker.
public abstract class TestBase
  // ...
  <T> T cookieRequest(Function<RequestSender, ValidatableResponse> exec, Function<ValidatableResponse, T> post) {

        ValidatableResponse vr = exec.apply(request());
        saveGlobalCookies(vr.extract().detailedCookies());
        return post.apply(vr);

    }
}
public class ActualTest extends TestBase {
  @Test
  public void test1() {
    String content = cookieRequest(r->r.get("/some").then(),
       r->r.extract().body().asString());
  }
}
  1. Instantiate extended instances of ResponseSpecificationImpl (dragging in RequestSpecificationImpl and TestSpecificationImpl).

Upvotes: 0

Views: 2177

Answers (1)

lucas-nguyen-17
lucas-nguyen-17

Reputation: 5917

You can use CookieFilter to satify your need.

The cookie filter can be used to keep track of all the cookies sent by the server and use them in subsequent requests

You can use this class in 2 ways:

  1. Static setting:
RestAssured.filters(new CookieFilter());
  1. Specify for request you want:
CookieFilter cookieFilter = new CookieFilter();

//Request 1  
given().filter(cookieFilter).get("/x");

//Request 2
given().filter(cookieFilter).get("/y");

For more information:

Upvotes: 2

Related Questions