== Rest-Assured integration

Rest-Assured is a Java DSL for easy testing of REST services.
An example of how to make a GET request and validate the JSON or XML response might be like:

`get("/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));`


The problem with Rest Assured is that by default it assumes that host is _localhost_ and port _8080_.
This might be perfect when not using Docker but when using docker this assumptions might not be the most typical.

For example, you may use another bind port rather than _8080_, you can expose 8080 port but bind to another port.
Also, you might run docker host in different ip rather than _localhost_, maybe because you are using an external docker host.

So in these cases you need to set in every request:

`get("http://myhost.org:5000/lotto").then().assertThat().body("lotto.lottoId", equalTo(5));`

or you can also configure Rest-Assured:

----
RestAssured.baseURI = "http://myhost.org";
RestAssured.port = 5000;
----

or using RequestSpecBuilder

----
spec = new RequestSpecBuilder()
            .setContentType(ContentType.JSON)
            .setBaseUri("http://localhost:8080/")
            .build();
----

=== Why integration with Cube?

Previous approach works but it has some problems:

* You need to repeat the same configuration properties in all tests you want to use Rest-Assured with Docker.
* Requires some development interference of the developer, if it is running in docker machine one _ip_ must be set which might change in the future,
 or changed to _localhost_ if running on native linux.
* Any change on Rest-Assured configuration properties would make all tests fails.

To fix these problems, you can use Arquillian Cube Docker RestAssured integration which creates a `RequestSpecBuilder`
with correct values set.

=== Configuration

==== Dependencies

To use Arquillian Cube RestAssured integration you only need to add as dependency.

[source, xml]
.pom.xml
----
<dependency>
     <groupId>org.arquillian.cube</groupId>
     <artifactId>arquillian-cube-docker-restassured</artifactId>
    <scope>test</scope>
</dependency>
----

==== Configuration Parameters

By default, if your scenario is not complex you don't need to configure anything else, but this extension also contains some configuration parameters that can be used.

[cols="2,2,5a", options="header"]
|===
|Attribute
|Default Value
|Description

|baseUri
|<schema>://<dockerhost>
|It is the base uri used in RestAssured. You can set a specific value or not set and let extension configure it by
default using auto-resolution system.

|schema
|http
|Schema used in case of auto-resolution of baseUri

|port
|If from all running containers there is only one binding port (notice that exposed ports are not bound if not specified),
then this is the value used. If there are more than one binding port then an exception is thrown.
|Port to be used for communicating with docker host. By default, this port must be the exposed port used in port binding.
The extension will resolve for given exposed port which is the binding port. If it is not found then exposed port will
be assumed as binding port too. For example using -p 8080:80 you need to set this property to 80 and extension will resolve to 8080.

|exclusionContainers
|
|If you want to use auto-resolution of the port attribute you might want to exclude that extension searches for binding
ports in some containers (for example monitoring containers). This is a CSV property to set container names of al of them.

|basePath
|
|Base path (context) of the application

|useRelaxedHttpsValidation
|
|Configures RestAssured to use relaxed https validation. If attribute is present but with no value then it is applied to
all protocols. If you put a string, only this protocol will be applied the relaxed rules.

|authenticationScheme
|
|Sets the authentication scheme. Possible values are:
* `basic:username:password` for basic auth.
* `form:username:password` for from auth.
* `preemptive:username:password`.
* `certificate:url:password` for cert auth.
* `digest:username:password` for digest auth.
* `oauth:consumerKey:consumerSecret:accessToken:secretToken` for oauth 1.
* `oauth2:accessToken` for oauth 2.
|===

For example:

[source, xml]
.arquillian.xml
----
<extension qualifier="restassured">
    <property name="port">80</property>
</extension>
----

IMPORTANT: You can set any extension property using system properties or environment variables, this can be really helpful in case of setting authentication scheme and sensitive data. For example `arq.extension.restassured.basePath=helloworld` for setting `basePath` property.

You can also use `@DockerUrl` enrichment for configuring the `RequestSpecBuilder` instead of relaying to `arquillian.xml`.

[source, java]
----
@DockerUrl(containerName = "pingpong", exposedPort = 8080)
@ArquillianResource
RequestSpecBuilder requestSpecBuilder;
----

==== Example

After setting the dependency and configuring the extension, if required you can write your Arquillian Cube test as
usually and use RestAssured without configuring it.

For example, with the following docker compose file which starts a `ping-pong` server listening at root context:

[source, yml]
.docker-compose.yml
----
helloworld:
  image: tsongpon/pingpong
  ports:
    - "8080:8080"
----

you only need to do:

[source, java]
.PingPongTest.java
----
@RunWith(Arquillian.class)
public class PingPongTest {

    @ArquillianResource
    @DockerUrl(containerName = "helloworld", exposedPort = 8080)
    RequestSpecBuilder requestSpecBuilder;

    @Test
    public void should_receive_ok_message() throws MalformedURLException, InterruptedException {
        RestAssured
            .given()
            .spec(requestSpecBuilder.build())
            .when()
            .get()
            .then()
            .assertThat().body("status", equalTo("OK"));
    }

}
----

Notice that no _ip_ nor _port_ configuration are required since everything is managed and configured by Cube.

You can see full example at: https://github.com/arquillian/arquillian-cube/tree/main/docker/ftest-restassured
