├── .gitignore
├── Readme.md
├── docker-files
├── docker-compose-ecommerce.yml
└── docker-compose-restfulbooker.yml
├── pom.xml
├── src
└── test
│ └── java
│ └── io
│ └── github
│ └── mfaisalkhatri
│ ├── restfulbooker
│ ├── testdata
│ │ ├── AuthData.java
│ │ ├── BookingData.java
│ │ ├── BookingDates.java
│ │ ├── PartialUpdateBookingData.java
│ │ └── TestDataBuilder.java
│ └── tests
│ │ ├── BaseTest.java
│ │ └── RestfulBookerTests.java
│ └── restfulecommerce
│ ├── pojo
│ └── Order.java
│ └── tests
│ └── AddOrderTests.java
└── testng.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/modules.xml
8 | .idea/jarRepositories.xml
9 | .idea/compiler.xml
10 | .idea/libraries/
11 | *.iws
12 | *.iml
13 | *.ipr
14 |
15 | ### Eclipse ###
16 | .apt_generated
17 | .classpath
18 | .factorypath
19 | .project
20 | .settings
21 | .springBeans
22 | .sts4-cache
23 |
24 | ### Mac OS ###
25 | .DS_Store
26 |
27 | .idea/
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ## Don't forget to give a :star: to make the project popular.
4 |
5 | ## :question: What is this Repository about?
6 |
7 | - This repository contains the code that was demonstrated on the YouTube LIVE Session on API Testing using REST-Assured
8 |
9 | ## :briefcase: What does this repo contain?
10 |
11 | - This repo contains example codes of API Tests using Rest-Assured
12 | - `Hamcrest Matchers` are used for assertions
13 | - [Datafaker](https://www.datafaker.net/) for test data generation
14 | - Tests are written using the [Restful Booker APIs](https://restful-booker.herokuapp.com/apidoc/index.html)
15 |
16 | ## :hammer_and_wrench: Talking more about the Scenarios Covered in this project:
17 |
18 | You will get the answers to the following questions and its respective working code example with rest-assured
19 | framework in this repository:
20 |
21 | - How to write tests for `Get` requests?
22 | - How to write tests for `POST` requests?
23 | - How to write tests for `PUT` requests?
24 | - How to write tests for `PATCH` requests?
25 | - How to write tests for `DELETE` requests?
26 | - How to handle the `authentication` requests?
27 | - How to use RequestSpecification in Rest-Assured?
28 | - How to use ResponseSpecification in Rest-Assured?
29 | - How to verify the Response Body?
30 | - How to verify the Response Status Code?
31 | - How to verify the Response headers using ResponseSpecification?
32 | - How to perform assertions using `Hamcrest Matchers`?
33 | - How to use _JAVA RECORDS_ for passing values to POST, PUT and PATCH request body?
34 | - How to use [Datafaker](https://www.datafaker.net/) for generating random fake test data and use it in automated tests?
35 | - Performing End to End testing of the Restful-booker APIs
36 |
37 | ## :computer: Blog and Video Links
38 |
39 | - [What is API Testing?](https://mfaisalkhatri.github.io/2020/08/08/apitesting/)
40 | - [End to End API testing using rest-assured](https://medium.com/@iamfaisalkhatri/end-to-end-api-testing-using-rest-assured-a58c4ea80255)
41 |
42 | ## :movie_camera: Tutorial Video
43 |
44 | [](https://www.youtube.com/watch?v=xLKpdQE0oKY&t=1s)
45 | [](https://www.youtube.com/live/AFQSolEeu74?si=8WROMbunjUuzqqQj&t=1)
46 |
47 | ## :question: Need Assistance?
48 |
49 | - Discuss your queries by writing to me @ `mohammadfaisalkhatri@gmail.com`
50 | OR ping me on any of the social media sites using the below link:
51 | - [Linktree](https://linktr.ee/faisalkhatri)
52 |
53 | ## :thought_balloon: Checkout the blogs related to Testing written by me on the following links:
54 |
55 | - [Medium Blogs](https://medium.com/@iamfaisalkhatri)
56 | - [LambdaTest Blogs](https://www.lambdatest.com/blog/author/mfaisalkhatri/)
57 | - [My Website](https://mfaisalkhatri.github.io)
58 |
59 | ## Subscribe to my [YouTube Channel](https://www.youtube.com/@faisalkhatriqa)
60 |
61 |
--------------------------------------------------------------------------------
/docker-files/docker-compose-ecommerce.yml:
--------------------------------------------------------------------------------
1 | # To execute this docker-compose yml file use `docker compose -f docker-files/docker-compose-ecommerce.yml up -d`
2 | # Add the `-d` flag at the end for detached execution
3 | # To stop the execution, hit Ctrl+C, and then `docker compose -f docker-files/docker-compose-ecommerce.yml down`
4 | services:
5 | restful-ecommerce:
6 | image: mfaisalkhatri/restful-ecommerce-app
7 | ports:
8 | - 3004:3004
--------------------------------------------------------------------------------
/docker-files/docker-compose-restfulbooker.yml:
--------------------------------------------------------------------------------
1 | # To execute this docker-compose yml file use `docker-compose -f docker-files/docker-compose-restfulbooker.yml up -d`
2 | # Add the `-d` flag at the end for detached execution
3 | # To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-files/docker-compose-restfulbooker.yml down`
4 | version: "3"
5 | services:
6 | restful-booker:
7 | image: mwinteringham/restfulbooker
8 | ports:
9 | - 3001:3001
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | io.github.mfaisalkhatri
6 | api-testing-rest-assured
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | api-testing-rest-assured
11 | http://maven.apache.org
12 |
13 | UTF-8
14 | 7.10.2
15 | 5.5.0
16 | 1.3
17 | 2.18.1
18 | 2.4.1
19 | 3.11.0
20 | 3.1.2
21 | 17
22 | testng.xml
23 |
24 |
25 |
26 |
27 | org.testng
28 | testng
29 | ${testng.version}
30 |
31 |
32 | io.rest-assured
33 | rest-assured
34 | ${rest-assured.version}
35 | test
36 |
37 |
38 | com.fasterxml.jackson.core
39 | jackson-databind
40 | ${jackson-databind.version}
41 |
42 |
43 | org.hamcrest
44 | hamcrest-all
45 | ${hamcrest-all.version}
46 |
47 |
48 |
49 | net.datafaker
50 | datafaker
51 | ${data-faker.version}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-compiler-plugin
61 | ${maven-compiler-plugin.version}
62 |
63 | ${java-release.version}
64 | UTF-8
65 | true
66 |
67 |
68 |
69 | org.apache.maven.plugins
70 | maven-surefire-plugin
71 | ${maven-surefire-plugin.version}
72 |
73 |
74 |
75 | test
76 |
77 |
78 |
79 |
80 |
81 | ${suite-xml}
82 |
83 | -Dfile.encoding=UTF-8 -Xdebug -Xnoagent
84 |
85 | -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/testdata/AuthData.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.testdata;
2 |
3 | public record AuthData(String username, String password) {
4 | }
5 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/testdata/BookingData.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.testdata;
2 |
3 | public record BookingData(String firstname, String lastname, int totalprice, boolean depositpaid,
4 | BookingDates bookingdates, String additionalneeds) { }
5 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/testdata/BookingDates.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.testdata;
2 |
3 | public record BookingDates(String checkin, String checkout) {
4 | }
5 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/testdata/PartialUpdateBookingData.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.testdata;
2 |
3 | public record PartialUpdateBookingData(int totalprice, String additionalneeds) {
4 | }
5 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/testdata/TestDataBuilder.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.testdata;
2 |
3 | import net.datafaker.Faker;
4 |
5 | import java.text.SimpleDateFormat;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | public class TestDataBuilder {
9 |
10 | private static final Faker FAKER = new Faker();
11 |
12 | public static BookingData getBookingData() {
13 | final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
14 | final BookingDates bookingDates = new BookingDates(simpleDateFormat.format(FAKER.date().past(20, TimeUnit.DAYS)), simpleDateFormat.format(FAKER.date().future(10, TimeUnit.DAYS)));
15 |
16 | return new BookingData(FAKER.name().firstName(), FAKER.name().lastName(),
17 | FAKER.number().numberBetween(50, 2000), true, bookingDates, FAKER.food().dish());
18 | }
19 |
20 | public static AuthData getAuthData() {
21 | return new AuthData("admin", "password123");
22 | }
23 |
24 | public static PartialUpdateBookingData getPartialUpdateBookingData() {
25 | return new PartialUpdateBookingData(FAKER.number().numberBetween(2000, 3000),FAKER.food().fruit());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/tests/BaseTest.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.tests;
2 |
3 | import io.restassured.builder.RequestSpecBuilder;
4 | import io.restassured.builder.ResponseSpecBuilder;
5 | import io.restassured.filter.log.RequestLoggingFilter;
6 | import io.restassured.filter.log.ResponseLoggingFilter;
7 | import io.restassured.specification.RequestSpecification;
8 | import io.restassured.specification.ResponseSpecification;
9 |
10 | public class BaseTest {
11 |
12 | protected static RequestSpecification requestSpec() {
13 | final RequestSpecBuilder requestBuilder = new RequestSpecBuilder();
14 | return requestBuilder.addHeader("Content-Type", "application/json")
15 | .addHeader("Accept", "application/json")
16 | .addFilter(new RequestLoggingFilter())
17 | .addFilter(new ResponseLoggingFilter())
18 | .setBaseUri("http://localhost:3001").build();
19 | }
20 |
21 | protected static ResponseSpecification responseSpec() {
22 | final ResponseSpecBuilder responseBuilder = new ResponseSpecBuilder();
23 | return responseBuilder.expectStatusCode(200)
24 | .expectHeader("Content-Type", "application/json; charset=utf-8")
25 | .build();
26 |
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulbooker/tests/RestfulBookerTests.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulbooker.tests;
2 |
3 | import static io.github.mfaisalkhatri.restfulbooker.testdata.TestDataBuilder.getAuthData;
4 | import static io.github.mfaisalkhatri.restfulbooker.testdata.TestDataBuilder.getBookingData;
5 | import static io.github.mfaisalkhatri.restfulbooker.testdata.TestDataBuilder.getPartialUpdateBookingData;
6 | import static io.restassured.RestAssured.given;
7 | import static org.hamcrest.Matchers.equalTo;
8 | import static org.hamcrest.Matchers.is;
9 | import static org.hamcrest.Matchers.notNullValue;
10 |
11 | import io.github.mfaisalkhatri.restfulbooker.testdata.AuthData;
12 | import io.github.mfaisalkhatri.restfulbooker.testdata.BookingData;
13 | import io.github.mfaisalkhatri.restfulbooker.testdata.PartialUpdateBookingData;
14 | import org.testng.annotations.BeforeClass;
15 | import org.testng.annotations.Test;
16 |
17 | public class RestfulBookerTests extends BaseTest {
18 |
19 | private BookingData bookingData;
20 | private int bookingId;
21 | private String token;
22 |
23 | @BeforeClass
24 | public void setup() {
25 | this.bookingData = getBookingData();
26 | }
27 |
28 | @Test
29 | public void testCreateBooking() {
30 | this.bookingId = given().spec(requestSpec())
31 | .body(this.bookingData)
32 | .when()
33 | .post("/booking")
34 | .then()
35 | .spec(responseSpec())
36 | .and()
37 | .assertThat()
38 | .body("bookingid", is(notNullValue()))
39 | .body("booking.firstname", equalTo(this.bookingData.firstname()))
40 | .body("booking.bookingdates.checkin", equalTo(this.bookingData.bookingdates().checkin()))
41 | .extract()
42 | .path("bookingid");
43 | }
44 |
45 | @Test
46 | public void testGetBooking() {
47 | given().spec(requestSpec())
48 | .when()
49 | .get("/booking/" + this.bookingId)
50 | .then()
51 | .spec(responseSpec());
52 | }
53 |
54 | @Test
55 | public void testUpdateBooking() {
56 | final BookingData updateBooking = getBookingData();
57 |
58 | given().spec(requestSpec())
59 | .header("Cookie", "token=" + this.token)
60 | .body(updateBooking)
61 | .when()
62 | .put("/booking/" + this.bookingId)
63 | .then()
64 | .spec(responseSpec());
65 | }
66 |
67 | @Test
68 | public void testUpdatePartialBooking() {
69 |
70 | final PartialUpdateBookingData partialUpdateData = getPartialUpdateBookingData();
71 |
72 | given().spec(requestSpec())
73 | .header("Cookie", "token=" + this.token)
74 | .body(partialUpdateData)
75 | .when()
76 | .patch("/booking/" + this.bookingId)
77 | .then()
78 | .spec(responseSpec())
79 | .body("additionalneeds", equalTo(partialUpdateData.additionalneeds()));
80 | }
81 |
82 | @Test
83 | public void testDeleteBooking() {
84 | given().spec(requestSpec())
85 | .header("Cookie", "token=" + this.token)
86 | .when()
87 | .delete("/booking/" + this.bookingId)
88 | .then()
89 | .statusCode(201);
90 | }
91 |
92 | @Test
93 | public void testDeletedBooking() {
94 | given().spec(requestSpec())
95 | .when()
96 | .get("/booking/" + this.bookingId)
97 | .then()
98 | .statusCode(404);
99 | }
100 |
101 |
102 | @Test
103 | public void testTokenGeneration() {
104 |
105 | final AuthData authData = getAuthData();
106 |
107 | this.token = given().spec(requestSpec())
108 | .body(authData)
109 | .when()
110 | .post("/auth")
111 | .then()
112 | .spec(responseSpec())
113 | .and()
114 | .assertThat()
115 | .body("token", is(notNullValue()))
116 | .extract().path("token");
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulecommerce/pojo/Order.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulecommerce.pojo;
2 |
3 | public record Order(String user_id, String product_id, String product_name, int product_amount, int qty, int tax_amt,
4 | int total_amt) {
5 | }
6 |
--------------------------------------------------------------------------------
/src/test/java/io/github/mfaisalkhatri/restfulecommerce/tests/AddOrderTests.java:
--------------------------------------------------------------------------------
1 | package io.github.mfaisalkhatri.restfulecommerce.tests;
2 |
3 | import static io.restassured.RestAssured.given;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | import io.github.mfaisalkhatri.restfulecommerce.pojo.Order;
9 | import io.restassured.http.ContentType;
10 | import org.testng.annotations.Test;
11 |
12 | public class AddOrderTests {
13 |
14 | @Test
15 | public void testAddOrder () {
16 | List orders = new ArrayList<> ();
17 | orders.add (new Order ("1", "34", "Canon Camera CX12", 14500, 1, 915, 15415));
18 |
19 | given ().body (orders)
20 | .when ()
21 | .log ()
22 | .all ()
23 | .contentType (ContentType.JSON)
24 | .post ("http://localhost:3004/addOrder")
25 | .then ()
26 | .log ()
27 | .all ()
28 | .statusCode (201);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/testng.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------