Why RequestSpecification?
Observe the below lines of codes carefully. You will find that we have some common statements in both @Test methods after given() method call.
package RequestSpecificationExamples;
import org.testng.annotations.Test;
import io.restassured.RestAssured;
public class WithoutUsingRequestSpecification {
@Test
public void getAllBookings()
{
// Given
RestAssured
.given()
// Common baseURI and basePath
.baseUri("https://restful-booker.herokuapp.com")
.basePath("/booking")
// When
.when()
// Then
.then()
.statusLine("HTTP/1.1 200 OK");
}
@Test
public void getBookingDetailsWithInvalidFirstName()
{
// Given
RestAssured
.given()
// Common baseURI and basePath
.baseUri("https://restful-booker.herokuapp.com")
.basePath("/booking")
.param("firstName", "Rahul")
// When
.when()
// Then
.then()
.statusLine("HTTP/1.1 200 OK");
}
}
Above we have only two tests but in real-time you may have many. A group of tests will have some common specifications to create a request. Following the DRY principle is the best way to write clean code. We have repeated common request specifications in both tests which is not a good practice. If we need to modify then we need to make changes every placed used.
To club common request specifications together and put as a common entity, we can use RequestSpecification in Rest Assured. RequestSpecification is an interface that allows you to specify how the request will look like. This interface has readymade methods to define base URL, base path, headers, etc. We need to use given() method of RestAssured class to get a reference for RequestSpecification. Remember RequestSpecification is an interface and we can not create an object of it. RequestSpecificationImpl is its implemented class.
How to use RequestSpecification?
A RequestSpecification with some specifications can be created as below:-
RequestSpecification requestSpecification = RestAssured.given();
requestSpecification.baseUri("https://restful-booker.herokuapp.com")
requestSpecification.basePath("/booking");
Or instead of calling RequestSpecification reference multiple times, we can use the builder pattern as below:-
RequestSpecification requestSpecification =
RestAssured.given()
.baseUri("https://restful-booker.herokuapp.com")
.basePath("/booking");
We can add a RequestSpecification to a request in multiple ways as shown below:-
RestAssured.given(requestSpecification)
OR
RestAssured.given().spec(requestSpecification)
Example Program
package RequestSpecificationExamples;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSpecification;
public class WithRequestSpecification {
RequestSpecification requestSpecification;
@BeforeClass
public void setupRequestSpecification()
{
requestSpecification = RestAssured.given()
.baseUri("https://restful-booker.herokuapp.com")
.basePath("/booking");
}
@Test
public void getAllBookings()
{
// Given
RestAssured
.given()
.spec(requestSpecification)
// When
.when()
// Then
.then()
.statusLine("HTTP/1.1 200 OK");
}
@Test
public void getBookingDetailsWithInvalidFirstName()
{
// Given
RestAssured
.given(requestSpecification)
.param("firstName", "Rahul")
// When
.when()
// Then
.then()
.statusLine("HTTP/1.1 200 OK");
}
}
There are two methods in RestAssured class to start creating Request specifications:-
- given()
- with()
The return type of both methods is RequestSpecification. There is no difference between the above two methods. The only difference is syntactical. An example code is below:-
package RequestSpecificationExamples;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
public class RequestSpecificationExample {
public static void main(String[] args) {
// Creating request specification using given()
RequestSpecification request1 = RestAssured.given();
// Setting Base URI
request1.baseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
request1.basePath("/booking");
// Creating request specification using with()
RequestSpecification request2 = RestAssured.with();
// Setting Base URI
request2.baseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
request2.basePath("/ping");
// You can also use builder pattern as below
RequestSpecification request3 = RestAssured.with();
request3.baseUri("https://restful-booker.herokuapp.com").basePath("/ping");
}
}
Multiple Ways Of Calling HTTP Methods On A RequestSpecification
Rest Assured is that you have multiple ways of performing the same action which makes beginner confused. Rest Assured is full of syntactic sugar methods.
See the example program below to understand different ways of calling http methods on RequestSpecification :-
package RestAssuredConcepts;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
public class DifferentWaysOfCallingHttpMethodsOnRequestSpecifications {
public static void main(String[] args) {
// Creating request specification using given()
RequestSpecification request1= RestAssured.given();
// Setting Base URI
request1.baseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
request1.basePath("/booking");
// We can directly call http verbs on RequestSpecification
Response res1= request1.get();
System.out.println(res1.asString());
// We can also pass RequestSpecification reference variable in overloaded given() method
Response res2 = RestAssured.given(request1).get();
System.out.println(res2.asString());
// We can also pass RequestSpecification using spec() method
Response res3 = RestAssured.given().spec(request1).get();
System.out.println(res3.asString());
}
}
Output
[{"bookingid":13},{"bookingid":5},{"bookingid":11},{"bookingid":10},{"bookingid":8},{"bookingid":4},{"bookingid":3},{"bookingid":1},{"bookingid":6},{"bookingid":7},{"bookingid":9},{"bookingid":2},{"bookingid":12}]
[{"bookingid":13},{"bookingid":5},{"bookingid":11},{"bookingid":10},{"bookingid":8},{"bookingid":4},{"bookingid":3},{"bookingid":1},{"bookingid":6},{"bookingid":7},{"bookingid":9},{"bookingid":2},{"bookingid":12}]
[{"bookingid":13},{"bookingid":5},{"bookingid":11},{"bookingid":10},{"bookingid":8},{"bookingid":4},{"bookingid":3},{"bookingid":1},{"bookingid":6},{"bookingid":7},{"bookingid":9},{"bookingid":2},{"bookingid":12}]
Building RequestSpecification Using RequestSpecBuilder
We can create RequestSpecification using RequestSpecBuilder as well. RequestSpecBuilder is a class in Rest Assured, which contains method to set cookies, headers, multipart details, body, authentication, form parameters, query parameters, path parameters, base path, base URI, proxy etc. These all are required to construct a Requestspecification. After adding all required details, we can use “build()” method of RequestSpecBuilder class to get RequestSpecification reference. Now we can use it as required and we have seen them already.
Rest Assured Example:-
package RestAssuredConcepts;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
public class RequestSpecBuilderExample {
public static void main(String[] args) {
// Creating an object of RequestSpecBuilder
RequestSpecBuilder reqBuilder = new RequestSpecBuilder();
// Setting Base URI
reqBuilder.setBaseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
reqBuilder.setBasePath("/booking");
// Getting RequestSpecification reference using builder() method
RequestSpecification reqSpec = reqBuilder.build();
// Usage in different styles
// We can directly call http verbs on RequestSpecification
Response res1= reqSpec.get();
System.out.println(res1.asString());
// We can also pass RequestSpecification reference variable in overloaded given() method
Response res2 = RestAssured.given(reqSpec).get();
System.out.println(res2.asString());
// We can also pass RequestSpecification using spec() method
Response res3 = RestAssured.given().spec(reqSpec).get();
System.out.println(res3.asString());
}
}
Setting A Default RequestSpecification In Rest Assured
We know well now that we can create multiple Request Specification as per our need. Rest Assured provides a way to set a default Request Specification so that it can be sent to each request if no other Request Specification is set. In Java, default value of an int data type is zero. Similar to that we can set a Request Specification as default in Rest Assured.
To set a default Request Specification, we need to use static property “requestSpecification“of RestAssured class. When no other RequestSpecification is set to request, default RequestSpecification will be sent. If we set another request specification to the request, default request specification will be overridden by new one.
Rest Assured Code:-
package RestAssuredConcepts;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
public class DefaultRequestSpecificationExample {
@BeforeClass
public void setupDefaultRequestSpecification()
{
// Creating request specification using given()
RequestSpecification request1= RestAssured.given();
// Setting Base URI
request1.baseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
request1.basePath("/booking");
RestAssured.requestSpecification = request1;
}
@Test
public void useDefaultRequestSpecification()
{
// It will use default RequestSpecification
Response res = RestAssured.when().get();
System.out.println("Response for default: "+res.asString());
}
@Test
public void overrideDefaultRequestSpecification()
{
// Creating request specification using with()
RequestSpecification request2= RestAssured.with();
// Setting Base URI
request2.baseUri("https://restful-booker.herokuapp.com");
// Setting Base Path
request2.basePath("/ping");
// Overriding default request specification
Response res = RestAssured.given().spec(request2).get();
System.out.println("Response for overriding: "+res.asString());
}
}
Output:
Response for overriding: Created
Response for default: [{"bookingid":7},{"bookingid":5},{"bookingid":9},{"bookingid":3
Querying RequestSpecification In Rest Assured
We know that RequestSpecification is used to create a request or how the request will look like. We set base URI, base path, headers, etc to request using RequestSpecification. There is a way available to query this RequestSpecification as well so that at any point of time we can retrieve details of RequestSpecification like what is base URI is set etc.
To query or retrieve details from RequestSpecification, Rest Assured provides a class named SpecificationQuerier. This class has a static method called query(RequestSpecification specification) which returns reference of QueryableRequestSpecification interface. This interface has methods to retrieve request details such as getBasePath(), getBody() etc.
Rest Assured Program:-
package RestAssuredConcepts;
import io.restassured.RestAssured;
import io.restassured.http.Header;
import io.restassured.http.Headers;
import io.restassured.specification.QueryableRequestSpecification;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.SpecificationQuerier;
public class QueryingRequestSpecificationExample {
public static void main(String[] args) {
// I am adding dummy request details for example
String JsonBody = "{\"firstName\":\"Amod\"}";
// Creating request specification using given()
RequestSpecification request1= RestAssured.given();
// Setting Base URI
request1.baseUri("https://restful-booker.herokuapp.com")
// Setting Base Path
.basePath("/booking")
.body(JsonBody)
.header("header1", "headerValue1")
.header("header2", "headerValue2");
// Querying RequestSpecification
// Use query() method of SpecificationQuerier class to query
QueryableRequestSpecification queryRequest = SpecificationQuerier.query(request1);
// get base URI
String retrieveURI = queryRequest.getBaseUri();
System.out.println("Base URI is : "+retrieveURI);
// get base Path
String retrievePath = queryRequest.getBasePath();
System.out.println("Base PATH is : "+retrievePath);
// get Body
String retrieveBody = queryRequest.getBody();
System.out.println("Body is : "+retrieveBody);
// Get Headers
Headers allHeaders = queryRequest.getHeaders();
System.out.println("Printing all headers: ");
for(Header h : allHeaders)
{
System.out.println("Header name : "+ h.getName()+" Header value is : "+h.getValue());
}
}
}
Output:
Base URI is : https://restful-booker.herokuapp.com
Base PATH is : /booking
Body is : {"firstName":"Amod"}
Printing all headers:
Header name : header1 Header value is : headerValue1
Header name : header2 Header value is : headerValue2