REST Assured's Fluent Interface Design (Java) 
Two topics that I haven't seen explained very well in the tutorials and videos that I've watched about the 
REST Assured testing library are: 
-  Q: Why is its API designed the way it is? (A: It uses a Fluent interface design.)
-  Q: How does its Gherkin-like syntax actually work? (A: Its methods all return the interfaces most likely to be needed next.)
 
I'll explore these questions in more detail below.
This article assumes that you're already familiar with the basics of 
Java and have a general idea of what Behavior-Driven Development is and what test code that uses REST Assured looks like. For example:
given().
    param(...).
when().
    get(...).
then().
    statusCode(200);
  Typical Java APIs 
A typical object-oriented API in Java consists of: 
-  a set of interfaces (or classes) that represent concepts related to the problem you're solving, and
-  methods on those interfaces that let you perform related actions.
Here's an example of a typical API in Java. Assume we have an application that deals with customers and customer orders, and assume that one order can contain multiple items. The application might provide an API that includes interfaces representing Customers, Orders, and Order Lines, and lets us create an order for a customer programmatically like this:
1  public void createAnOrder_Typical(Customer customer) {
2      Order order = new Order();                     // create a new, empty "order" object
3      customer.addOrder(order);                      // call the Customer's "addOrder" method to associate the new order with the given customer
4      OrderLine line1 = new OrderLine(5, "apples");  // create a new "order line" object for five apples
5      order.addLine(line1);                          // call the Order's "addLine" method to add the apples to the new order
6      OrderLine line2 = new OrderLine(3, "bananas"); // create a new "order line" object for three bananas
7      order.addLine(line2);                          // add the bananas to the order
8  }
This code creates all the objects we need and then wires them up together, one step at a time. Note that the 
addOrder and 
addLine methods on lines 3,5,7 here don't return a value.
  Fluent APIs 
An application with an API designed in a "Fluent" style might let you accomplish the same thing like this:
1  public void createAnOrder_Fluent(Customer customer) {
2      customer.newOrder().     // call the Customer's "newOrder" method to associate a new empty order with the given customer
3          with(5, "apples").   // add five apples to the new order
4          and().               // and
5          with(3, "bananas");  // add three bananas to the order
6  }
The goal of an API that's designed like this is to be readable and to flow. Notice that if you just read the code, it reads almost like English. The syntax in this "fluent" example looks different from the "typical" example above, but it doesn't actually use any new Java language mechanisms. This version just uses plain old interfaces and methods like the version above, but it uses them differently.
In this code, the 
newOrder() method that you call on the 
customer object returns another object that represents the newly-created order, and this returned 
Order object provides methods named 
with and 
and that you can call to build up the customer's order. The trick is that all the methods here return values, which the methods in the "typical" example above didn't do. So after you call the 
newOrder() method on the 
Customer object here on line 2, you can immediately call another method (
with) on the 
Order object that 
newOrder() returned. And since 
with returns the newly-updated 
Order object too, you can immediately call another method on it, and so on.
A chain of method calls, where each method is invoked on the return value of the preceding method call, is called 
method chaining, and it's the technique that REST Assured uses to provide its Fluent API that lets you write BDD tests that read like Gherkin's Given-When-Then style.
Different people have different opinions about whether fluent interfaces in general are good or bad, and in what kinds of situations they make sense. Martin Fowler discusses this a bit in his 
FluentInterface article. The examples I gave above are simplified versions of his examples in this article.
  A State Diagram 
In a Fluent API, each method is invoked on an object, and always returns an object. So if we represent each method by an arrow drawn from its source object to its returned object, we can 
diagram the example API above like this:

This diagram says that when we have a 
Customer object, we can call the 
newOrder() method on it, and we'll get an 
Order object back. And when we have an 
Order object, we can call 
with(5,"apples") or 
and() on it and we'll get back the same 
Order object, ready for more method calls.
In this API, the 
and() method doesn't actually do anything. It just returns the 
Order object that you called it on. Its implementation would look like this:
public Order and() {
    return this;
}
This method's only purpose is to provide better flow when you're reading the source code. Calling it is entirely optional. REST Assured uses this technique in its API too. It provides 
and() (and a few other) methods that you can insert into your BDD method chain if you like without changing the meaning of your code at all. If you look at REST Assured's implementation, the source code for these methods is also just 
"return this;". In their documentation, they refer to these methods as "
syntactic sugar." We'll see more of these below.
  REST Assured's API 
When you write a Gherkin-style test that uses REST Assured, there are three main phases: 
-  Preparing the HTTP request.
-  Making the REST API call by sending the request and receiving the response.
-  Checking the response.
Each of these phases is handled by a different REST Assured interface, and the typical 
given().when().get().then().assertThat()... code sequence moves through each of these interfaces in order.
  An Overview Diagram 
As an example, we'll consider the following code on the left. A simplified overview diagram of the REST Assured fluent API is on the right.
	
		
			| given().
    param("name1", "Alice").
    and().
    param("name2", "Bob").
when().
    get("/getBirthday/").
then().
    assertThat().
    statusCode(200); |   | 
	
We begin by calling 
given(). This method is 
static, which means we don't have to call it on an object; we can just call it directly. It returns a REST Assured 
RequestSpecification object that lets us start preparing our HTTP request. (More precisely, it returns an object that implements the 
RequestSpecification interface.)
The 
RequestSpecification object is responsible for preparing the HTTP request. It provides methods that let us specify properties of the request such as the base URI, parameters, content type, headers, and body. Each of these methods updates the 
RequestSpecification with the arguments we give it and then returns the updated 
RequestSpecification so we can call more methods on it.
The 
when() method actually does nothing. It's just syntactic sugar like the 
and() method we saw above. It helps us make our code read like Gherkin language syntax, but REST Assured doesn't actually require that we call it.
The 
RequestSpecification object is also used to make the actual RESTful API calls to the server using any of the HTTP request methods (GET, POST, etc.). In our example, we call 
.get("/getBirthday/"), which sends an HTTP GET request to the server using the request that we've prepared. The 
get(), 
post(), and related methods all send a request to the server and then return a REST Assured 
Response object that represents the HTTP response that the server returned.
The 
Response object provides methods to extract information about the HTTP response if you want to do that, but it doesn't actually provide any methods itself to do validation of the response. For that, it provides a 
then() method, which returns a 
ValidatableResponse object.
The 
ValidatableResponse object is responsible for performing validation (assertions) of the HTTP response. Its 
assertThat() method is just syntactic sugar that reads nicely between 
then() and the following assertion method calls. The 
ValidatableResponse provides methods to check the HTTP status code (which we do in this example), the headers, the response body, etc. These validation methods are described in other topics. Search for REST Assured in this wiki or on the Web for more info and tutorials.
Note that the set of methods that are available for us to call at any given point in our code depends on which particular interface we're dealing with at that point. So if we're dealing with a 
RequestSpecification object, we can call the 
param() method on it to set a request parameter, but we can't call 
statusCode() to check the response status code yet until we've made some other method calls and eventually gotten to the state where we're dealing with a 
ValidatableResponse object that provides this method. So a diagram like this is a way of illustrating the "grammar" that the fluent API allows. It shows which method calls are allowed to follow which other method calls.
  A More Detailed Diagram 
REST Assured's fluent API also lets you perform logging. For example, the syntax to write the body of an HTTP response to a log is 
.log().body(). When you call 
.log() on a 
ValidatableResponse object, it returns a new type of object, a 
ValidatableResponseLogSpec. At this point, the only methods that are available to call are methods that let you specify what kind of logging you want. For example, call 
.body() to log the response body, or call 
.headers() to log the response headers. These "log specification" methods return the 
ValidatableResponse object again, so they leave you back in the state you were in before you called 
.log(), and you can then continue validating the server's response with more assertion methods, or specify more logging.
REST Assured provides a similar kind of "detour" in its fluent grammar for specifying an authentication scheme to use in an HTTP request. When you're preparing your request and you call 
.auth() on the 
RequestSpecification, it returns an 
AuthenticationSpecification, which provides methods to specify an authentication scheme. These methods return back to the 
RequestSpecification so you can continue on from there. So for example, the code to specify a basic authentication scheme reads nicely: 
.auth().basic(userName, password). To explicitly specify that you want to use preemptive authentication, you can write 
.auth().preemptive().basic(userName, password). The API supports this option by detouring through a 
"PreemptiveAuthSpec" interface before returning back to the 
RequestSpecification.
Here's a more detailed diagram that includes some of the more commonly-used parts of REST Assured's fluent API:

-- 
BradChalfan - 17 Jul 2020