Mocking Solutions in Real-Time Applications - Notes By ShariqSP

Mocking Solutions in Real-Time Applications

What is Mocking? Mocking is a technique used in software testing to simulate the behavior of real objects in a controlled environment. Instead of relying on the actual implementation of dependencies, mock objects are used to mimic their behavior. This allows developers to isolate and test specific units of code without external dependencies like databases or APIs.

Mocking in the Payment Gateway API

In the payment gateway example, mocking can be used to test components such as the CardService or CardController without accessing the actual database. Mocking repositories like CardRepository allows the focus to remain on the service layer’s business logic.

Popular Mocking Frameworks

  • Mockito (most widely used)
  • EasyMock
  • JMock

Real-Time Mocking Example with Mockito

1. Mocking the CardService

Here, we will test the deposit method of the CardService without using the actual database. We will mock the CardRepository.

Applications of Mocking in Real-Time

  • Unit Testing: Isolates specific units for testing, ensuring the correctness of individual methods without external dependencies.
  • Integration Testing: Simulates external systems (e.g., APIs or databases) to test how components work together.
  • CI/CD Pipelines: Ensures reliable and fast testing in automated build pipelines by avoiding real external calls.
  • Error Simulation: Tests application behavior under failure conditions, such as database connection failures.

Benefits of Mocking

  • Faster test execution by eliminating the need for real system dependencies.
  • Improved test reliability by isolating the code under test.
  • Facilitates testing of edge cases and error scenarios.

By using mocking in the payment gateway API example, we ensure robust testing of the service and controller layers while avoiding reliance on a real database. This leads to faster, more reliable, and comprehensive testing, essential for building high-quality software.

Card Details

Below are the details of the cards associated with the payment gateway. These details include the card number, cardholder's name, and the current balance. The card details are used in various operations, such as deposits, withdrawals, and transaction history.

Card Information

Card Number Cardholder Name Balance
1234-5678-9012-3456 Shariq S P 1000.0
2345-6789-0123-4567 Mueen Shariff 1500.0
3456-7890-1234-5678 Irshan M E 2000.0
4567-8901-2345-6789 Rahul R 2500.0

click here for swagger documentation

Card Operations

The cards listed above can undergo various operations:

  • Deposit: Add money to the card.
  • Withdraw: Remove money from the card.
  • Transaction History: View the transaction history associated with the card.

Use the API endpoints to interact with the cards, such as performing deposits, withdrawals, or viewing transaction details.

Example: Viewing Card Details

To view the details of a specific card, use the GET /api/cards/{cardNumber} endpoint. This will return the card information, including the balance, cardholder name, and any associated transactions.

            
            GET http://apitesting.shariqsp.com:8080/api/cards/1234-5678-9012-3456
            
                

Example: Deposit Operation

To deposit money into a card, use the POST /api/cards/deposit endpoint. Below is an example request to deposit $500 into the card with the number 1234-5678-9012-3456:

            
            POST http://apitesting.shariqsp.com:8080/api/cards/deposit
            Content-Type: application/json

            {
                "cardNumber": "1234-5678-9012-3456",
                "amount": 500
            }
            
                

Example: Withdraw Operation

To withdraw money from a card, use the POST /api/cards/withdraw endpoint. Below is an example request to withdraw $300 from the card with the number 1234-5678-9012-3456:

            
            POST http://apitesting.shariqsp.com:8080/api/cards/withdraw
            Content-Type: application/json

            {
                "cardNumber": "1234-5678-9012-3456",
                "amount": 300
            }
            
                

Testing the Payment Gateway API with RestAssured

RestAssured is a Java library designed for testing RESTful APIs. It provides a domain-specific language (DSL) to write simple and readable test cases for API endpoints. Below, we demonstrate how to use RestAssured to test the Payment Gateway API created earlier.

Setup for RestAssured

Add the following dependency to your pom.xml file:

            
            
                io.rest-assured
                rest-assured
                5.3.0
                test
            
            
                

1. Testing the GET /api/cards/{cardNumber} Endpoint

We test retrieving a card by its card number.

            
            import io.restassured.RestAssured;
            import io.restassured.http.ContentType;
            import org.junit.jupiter.api.Test;

            import static io.restassured.RestAssured.*;
            import static org.hamcrest.Matchers.*;

            public class CardApiTest {

                @Test
                public void testGetCard() {
                    RestAssured.baseURI = "http://apitesting.shariqsp.com:8080/api/cards";

                    given()
                        .pathParam("cardNumber", "1234-5678-9012-3456")
                    .when()
                        .get("/{cardNumber}")
                    .then()
                        .statusCode(200)
                        .contentType(ContentType.JSON)
                        .body("cardHolderName", equalTo("Alice"))
                        .body("balance", equalTo(1000.0f));
                }
            }
            
                

2. Testing the POST /api/cards/deposit Endpoint

We test depositing money into a card.

            
            @Test
            public void testDeposit() {
                RestAssured.baseURI = "http://apitesting.shariqsp.com:8080/api/cards";

                given()
                    .contentType(ContentType.JSON)
                    .body("{ \"cardNumber\": \"1234-5678-9012-3456\", \"amount\": 500 }")
                .when()
                    .post("/deposit")
                .then()
                    .statusCode(200)
                    .body("balance", equalTo(1500.0f)); // Assuming the card initially had 1000 balance
            }
            
                

3. Testing the POST /api/cards/withdraw Endpoint

We test withdrawing money from a card.

            
            @Test
            public void testWithdraw() {
                RestAssured.baseURI = "http://apitesting.shariqsp.com:8080/api/cards";

                given()
                    .contentType(ContentType.JSON)
                    .body("{ \"cardNumber\": \"1234-5678-9012-3456\", \"amount\": 300 }")
                .when()
                    .post("/withdraw")
                .then()
                    .statusCode(200)
                    .body("balance", equalTo(700.0f)); // Assuming the card initially had 1000 balance
            }
            
                

4. Testing the GET /api/cards/{cardNumber}/transactions Endpoint

We test retrieving the transaction history of a card.

            
            @Test
            public void testGetTransactions() {
                RestAssured.baseURI = "http://apitesting.shariqsp.com:8080/api/cards";

                given()
                    .pathParam("cardNumber", "1234-5678-9012-3456")
                .when()
                    .get("/{cardNumber}/transactions")
                .then()
                    .statusCode(200)
                    .contentType(ContentType.JSON)
                    .body("size()", greaterThan(0)); // Assuming there are transactions in the system
            }
            
                

How RestAssured Works

RestAssured uses fluent APIs to build HTTP requests and assertions. The main components are:

  • Base URI: Specifies the root URL of the API being tested (e.g., http://apitesting.shariqsp.com:8080).
  • Given: Defines preconditions for the request, such as parameters or headers.
  • When: Sends the HTTP request (GET, POST, PUT, DELETE, etc.).
  • Then: Verifies the response using matchers (e.g., equalTo, greaterThan).

Benefits of Using RestAssured

  • Easy-to-read syntax for building tests.
  • Comprehensive support for HTTP methods, JSON/XML, and content-type assertions.
  • Integrates seamlessly with JUnit and other test frameworks.
  • Speeds up API testing by providing concise and robust assertions.

By using RestAssured to test the Payment Gateway API, we can ensure the correctness of all endpoints under various conditions, increasing confidence in the system’s stability and reliability.