├── .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 | ![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103) 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 | [![Watch the video](https://img.youtube.com/vi/xLKpdQE0oKY/hqdefault.jpg)](https://www.youtube.com/watch?v=xLKpdQE0oKY&t=1s) 45 | [![Watch the video](https://img.youtube.com/vi/AFQSolEeu74/hqdefault.jpg)](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 | --------------------------------------------------------------------------------