Multiple Catch Exceptions

HOME

In the previous tutorial, I have explained about the control flow of try catch and finally blocks in Java. In this tutorial, I’ll explain multiple catch exceptions. Java supports multiple catch exceptions, that means a try block can have more than one catch handlers. All catch blocks must be ordered from most specific to most general, i.e. catch for ArithmeticException must come before catch for Exception.

Scenario 1 In the below example, an array is defined of size 10 and we want to perform an invalid arithmetic operation on element 15 of the array. In this case, we have defined 3 different catch handlers to handle the exception – Arithmetic Exception, ArrayIndexOutOfBounds Exception and Parent Exception. The try block has thrown exception – Arithmetic as the Arithmetic operation is invalid (divide by 0).

public class MultipleCatchDemo1 {

	public static void main(String[] args) {
		try {
			int a[] = new int[10];
			a[15] = 30 / 0;
		
        } catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");
		
        } catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("ArrayIndexOutOfBounds Exception occurs");
		
        } catch (Exception e) {
			System.out.println("Parent Exception occurs");
		
        }
		System.out.println("Rest of the program");
	}
}

Scenario 2 – In the below example, I’m throwing an exception which is not handled by first catch exception handler.

public class MultipleCatchDemo2 {

	public static void main(String[] args) {

		try {
			int a[] = new int[10];
			System.out.println(a[15]);

		} catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");

		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("ArrayIndexOutOfBounds Exception occurs");

		} catch (Exception e) {
			System.out.println("Parent Exception occurs");

		}
		System.out.println("Rest of the program");
	}
}

Scenario 3 – In the below example, I’m throwing an exception which is not handled by any catch exception handler specified in the program. Then, parent exception handler will be invoked.

public class MultipleCatchDemo3 {

	public static void main(String[] args) {
		try {
			int a[] = new int[10];
			System.out.println(a[10]);

		} catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");
		
		} catch (NullPointerException e) {
			System.out.println("NullPointer Exception occurs");
		
		} catch (Exception e) {
			System.out.println("Parent Exception occurs");
		
		}
		System.out.println("Rest of the program");
	}
}

Scenario 4 – In the below example, we do not maintain the order of preference in exceptions (child to parent), then compile time error occurs.

public class MultipleCatchDemo4 {

	public static void main(String[] args) {
		try {
			int a[] = new int[10];
			System.out.println(a[10]);

		} catch (Exception e) {
			System.out.println("Parent Exception occurs");

		} catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");

		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("ArrayIndexOutOfBounds Exception occurs");

		}
		System.out.println("Rest of the program");
	}
}

Scenario 5 – In the below example, try block has 2 exceptions. It will call the first suitable catch block for the first try statement which has thrown the exception.

public class MultipleCatchDemo5 {

	public static void main(String[] args) {
		try {
			int a[] = new int[10];
			a[15] = 30 / 0;
			System.out.println(a[20]);

		} catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");

		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("ArrayIndexOutOfBounds Exception occurs");

		} catch (Exception e) {
			System.out.println("Parent Exception occurs");

		}
		System.out.println("Rest of the program");
	}
}

Similarly, if I interchanged the try statements as shown below the response will also changes.

public class MultipleCatchDemo6 {

	public static void main(String[] args) {
		try {
			int a[] = new int[10];
			System.out.println(a[20]);
			a[15] = 30 / 0;

		} catch (ArithmeticException e) {
			System.out.println("Arithmetic Exception occurs");

		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("ArrayIndexOutOfBounds Exception occurs");

		} catch (Exception e) {
			System.out.println("Parent Exception occurs");

		}
		System.out.println("Rest of the program");
	}
}

Flow control in try catch finally in Java

HOME

In this tutorial, I’ll explain about the flow control of try catch and finally blocks in accordance to the exception.

What is try block in Java?

It is used to specify a block where we should place exception code. The try block must be followed by either catch or finally. It means, we can’t use try block alone.
If an exception occurs at the particular statement of try block, the rest of the block code will not execute. So, it is recommended not to keeping the code in try block that will not throw an exception.

What is catch block in Java?

It is used to handle the exception by declaring the type of exception within the parameter. It must be preceded by try block which means we can’t use catch block alone. It can be followed by finally block later.
You can use multiple catch block with a single try block.

What is finally block in Java?

It is used to execute important statements such as establishing connection, stream, etc. It is always executed whether exception is handled or not.

Syntax of try-catch block

try{
//throw an exception
}catch{ //handle exception }

Syntax of try-catch-finally block

try{
//throw an exception
}catch { //handle exception }
finally { //important code which will always be executed  }

1.Exception occurs in try block and handled in catch block

If a statement in try block throws an exception, then rest of the code of try block is not executed. The control transfers to corresponding catch block. After the execution of code in catch block, the control moves to the rest of the program code to be executed.

public class TryCatchDemo {

	public static void main(String[] args) {
		{
			try {
				String a = null; // null value
				System.out.println(a.length());

				// This will never execute as try block has exception just above this statement
				System.out.println("Inside try block");

				// Exception will be handled in catch block and will execute the statements in
				// catch block
			} catch (NullPointerException e) {
				System.out.println("NullPointer Exception - Exception caught in Catch block");

			}

			// Rest of the program will be executed
			System.out.println("Outside try-catch block");
		}
	}
}

Output
NullPointer Exception - Exception caught in Catch block
Outside try-catch block

2. Exception occurs in try block and handled in catch block and finally block is present

If a statement in try block throws an exception, then rest of the code of try block is not executed. The control transfers to corresponding catch block. After the execution of code in catch block, the control moves to finally block (if present) and then the rest of the program is executed.

public class TryCatchFinallyDemo {

	public static void main(String[] args) {
		{
			try {
				String a = null; // null value
				System.out.println(a.length());

				// This will never execute as try block has exception just above this statement
				System.out.println("Inside try block");

				// Exception will be handled in catch block and will execute the statements in
				// catch block
			} catch (NullPointerException e) {
				System.out.println("NullPointer Exception - Exception caught in Catch block");

				// Statement present in finally block will be executed irrespective whether
				// exception is handled or not
			} finally {
				System.out.println("finally block executed");
			}

			// Rest of the program will be executed
			System.out.println("Outside try-catch block");
		}
	}
}

Output
NullPointer Exception - Exception caught in Catch block
finally block executed
Outside try-catch block

3. Exception occurred in try-block is not handled in catch block without finally block

If a statement in try block throws an exception, then rest of the code of try block is not executed.

public class TryNoCatchDemo {

	public static void main(String[] args) {
		{
			try {
				String a = null; // null value
				System.out.println(a.length());

				// This will never execute as try block has exception just above this statement
				System.out.println("Inside try block");

				// Incorrect Exception
			} catch (IndexOutOfBoundException e) {
				System.out.println("IndexOutOfBound Exception - Exception caught in Catch block");

			}


			// Rest of the program will be executed
			System.out.println("Outside try-catch block");
		}
	}
}

Output
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	IndexOutOfBoundException cannot be resolved to a type

	at JavaDemo.Exception.TryNoCatchDemo.main(TryNoCatchDemo.java:15)

4. Exception occurred in try-block is not handled in catch block with finally block

public class TryNoCatchFinallyDemo {

	public static void main(String[] args) {
		{
			try {
				String a = null; // null value
				System.out.println(a.length());

				// This will never execute as try block has exception just above this statement
				System.out.println("Inside try block");

				// Incorrect Exception
			} catch (IndexOutOfBoundException e) {
				System.out.println("IndexOutOfBound Exception - Exception caught in Catch block");

			}

			finally {
				System.out.println("finally block executed");
			}

			// Rest of the program will be executed
			System.out.println("Outside try-catch block");
		}
	}
}

Output
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	IndexOutOfBoundException cannot be resolved to a type

	at JavaDemo.Exception.TryNoCatchDemo.main(TryNoCatchDemo.java:15)

5. Exception doesn’t occur in try-block

If a statement in try block does not throw an exception, then catch block will be never executed and then rest of the program will be executed.

public class NoTryCatchDemo {

	public static void main(String[] args) {
		try {

			String str = "123";

			int num = Integer.parseInt(str);

			// this statement will execute
			// as no any exception is raised by above statement
			System.out.println("Inside try block");

		}

		catch (NumberFormatException ex) {

			System.out.println("catch block executed.");

		}

		System.out.println("Outside try-catch clause");
	}
}

Output
Inside try block
Outside try-catch clause

6. Exception doesn’t occur in try-block with finally block

If a statement in try block does not throw an exception, then catch block will never be executed. But the finally block will be executed and then rest of the program will be executed.

public class NoTryCatchFinallyDemo {

	public static void main(String[] args) {
		try {

			String str = "123";

			int num = Integer.parseInt(str);

			// this statement will execute
			// as no any exception is raised by above statement
			System.out.println("Inside try block");

		}

		catch (NumberFormatException ex) {

			System.out.println("catch block executed");

		} finally {
			System.out.println("finally block executed");
		}

		System.out.println("Outside try-catch clause");
	}
}

Output
Inside try block
finally block executed
Outside try-catch clause

Java Exceptions Tutorial: Built-in and User-defined Exceptions

HOME

Table of Contents

  1. These are exceptions that are checked at compile-time.
  2. They must be either handled using a try-catch block or declared in the method signature using the `throws` keyword.
  3. Examples include IOException, SQLException, and FileNotFoundException.

It is thrown when an exception has occurred in an arithmetic operation. Below is an example of this exception.

public class ArithmeticExceptionDemo {

	public static void main(String[] args) {
		{
			try {
				int a = 30, b = 0;
				int c = a / b; // cannot divide by zero
				System.out.println("Result = " + c);
			} catch (ArithmeticException e) {
				System.out.println("Can't divide a number by 0");
			}
		}
	}
}

2. ArrayIndexOutOfBoundsException

It is thrown when an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.

public class ArrayIndexOutOfBoundsExceptionDemo {

	public static void main(String[] args) {
		{
			try {
				// Create an array of size 5
				int a[] = new int[5];

				// Access 11th element from array of size 5
				a[10] = 9;
			} catch (ArrayIndexOutOfBoundsException e) {
				System.out.println("Array Index is Out Of Bounds");
			}
		}
	}
}

3. StringIndexOutOfBoundsException

It is thrown by String class methods to indicate that an index is either negative or greater than the size of the string.

public class StringOutOfBoundDemo {

	public static void main(String[] args) {
		{
			try {
				String a = "This is testing"; // length is 15
				System.out.println("Length of String :" + a.length());

				char b = a.charAt(20); // accessing 20th element
				System.out.println(b);
			} catch (StringIndexOutOfBoundsException e) {
				System.out.println("StringIndexOutOfBoundsException");
			}
		}
	}
}

4. NullPointerException

This exception is thrown when referring to the members of a null object.

public class NullPointerDemo {

	public static void main(String[] args) {
		{
			try {
				String a = null; // null value
				System.out.println(a.length());
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
		}
	}
}

5. NumberFormatException

This exception is thrown when a method can not convert a string into a numeric format.

public class NumberFormatDemo {

	public static void main(String[] args) {
		try {
			// "java" is not a number
			int num = Integer.parseInt("java");

			System.out.println(num);
		} catch (NumberFormatException e) {
			System.out.println("Number format exception");
		}
	}
}

6. FileNotFoundException

This Exception is thrown when a file is not accessible or does not open.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class FileNotFoundDemo {

	public static void main(String[] args) {
		try {

			// Following file does not exist
			File file = new File("C://demofile.txt");

			FileReader fr = new FileReader(file);
		} catch (FileNotFoundException e) {
			System.out.println("File does not exist");
		}
	}
}

7. ClassNotFoundException

This Exception is raised when we try to access a class whose definition is not found.

package JavaDemo;

public class ClassNotFoundExceptionDemo {

	public static void main(String[] args) {
		try {
			Class temp = Class.forName("gfg");
			// Calling the clas gfg which is not present in the
			// current class temp instance of calling class it
			// will throw ClassNotFoundException;
		} catch (ClassNotFoundException e) {
			// block executes when mention exception occur
			System.out.println("Class does not exist check the name of the class");
		}
	}
}

8. IOException

It is thrown when an input-output operation failed or interrupted.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class IOExceptionDemo {

	public static void main(String[] args) {

		String filepath = "C:\\Users\\Desktop\\IOTest1.txt";
		BufferedReader br1 = null;
		String curline;

		try {
			br1 = new BufferedReader(new FileReader(filepath));

			while ((curline = br1.readLine()) != null) {
				System.out.println(curline);
			}
		} catch (IOException e) {
			System.err.println("IOException found :" + e.getMessage());
		} finally {
			try {
				if (br1 != null)
					br1.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

9. NoSuchMethodException

It is thrown when accessing a method which is not found.

10. InterruptedException

It is thrown when a thread is waiting , sleeping , or doing some processing , and it is interrupted.

11. NoSuchFieldException

It is thrown when a class does not contain the field (or variable) specified.

12. RuntimeException

This represents any exception which occurs during runtime. They are ignored during compilation time. Such as logical bugs.

import java.util.Scanner;

public class RunTimeDemo {

	public static void main(String[] args) {
		// Reading user input
		Scanner input_dev = new Scanner(System.in);
		System.out.print("Enter your age in Numbers: ");
		int age1 = input_dev.nextInt();
		if (age1 > 20) {
			System.out.println("You can view the page");
		} else {
			System.out.println("You cannot view the page");
		}
	}
}

13. SQLException

This type of exception occurs while executing queries on a database related to the SQL syntax.

14. IllegalArgumentException

It is thrown when an inappropriate and incorrect argument is passed to the method. Suppose, a method does not allow null, but we are providing null as the parametr, then this exception is thrown.

Exception Handling in Java

HOME

What is Exception in Java?

An exception is an unwanted or unexpected event which occurs at the run time of the program, that leads to the disruption of the normal flow of execution of the program.

What is Exception Handling?

Exception Handling is a mechanism to handle runtime errors happen in the program such as ClassNotFoundException, IOException, SQLException, RemoteException, etc, which disruptes the normal execution of the program.

Suppose there are 6 statements in your program and there occurs an exception at statement 3, the rest of the code will not be executed i.e. statement 4 to 6 will not be executed. If we perform exception handling, the rest of the statement will be executed. That is why we use exception handling in Java.

What is the difference between Error and Exception?

Error: An Error indicates serious problem that a reasonable application should not try to catch. Error are used by the Java run-time system(JVM) to indicate errors having to do with the run-time environment itself(JRE) or StackOverflowError or OutOfMemoryError

Exception: Exception indicates conditions that a reasonable application might try to catch. Example of exceptions are IOException, SQLException, etc.

Types of Exceptions

1) Checked Exception
The classes which directly inherit Throwable class except RuntimeException and Error are known as checked exceptions e.g. IOException, SQLException etc. Checked exceptions are checked at compile-time.

2) Unchecked Exception
The classes which inherit RuntimeException are known as unchecked exceptions e.g. ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException etc. Unchecked exceptions are not checked at compile-time, but they are checked at runtime.

Hierarchy of Java Exception classes

Keywords used in Exception Handling in Java

1. try keyword – It is used to specify a block where we should place exception code. The try block must be followed by either catch or finally. It means, we can’t use try block alone.

2. catch keyword – It is used to handle the exception. It must be preceded by try block which means we can’t use catch block alone. It can be followed by finally block later.

3. finally keyword – It is used to execute the important code of the program irrespective the exception is handled or not.

4. throw keyword – It is used to throw an exception explicitly in the program inside a function or inside a block of code.

5. throws keyword – It is used to declare exceptions. It doesn’t throw an exception. It specifies that there may occur an exception in the method. It is always used with method signature.

Exception Handling Example in Java

Let’s see an example of exception handling where we can use try-catch block and will not use try-catch statements. Below example shows an exception without try-catch block.

package JavaDemo;

public class ExceptionHandlingDemo {

	static String a = null;

	public static void main(String[] args) {

		System.out.println(a.length());
	}

}

Output
Exception in thread "main" java.lang.NullPointerException
	at JavaDemo.ExceptionHandlingDemo.main(ExceptionHandlingDemo.java:9)

Below example shows an exception with try-catch block.

package JavaDemo;

public class ExceptionHandlingDemo {
	static String a = null;

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			System.out.println(a.length());
		} catch (NullPointerException e) {
			System.out.println(e);
		}
		System.out.println("Exception is handled");
	}

}

Output
java.lang.NullPointerException
Exception is handled

Cucumber Report Service

HOME

Reports can be generated in Cucumber in 2 ways.

  1. Generate report using Cucumber Report Services
  2. Generate local reports using built-in reporter plugins – html, json, junit, pretty

In this tutorial, I’ll explain about Cucumber Report Services. To use this service, we need to add Cucumber-jvm of version 6.7.0 and above.

<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-jvm</artifactId>
    <version>6.8.1</version>
    <type>pom</type>
</dependency>

Another important pre-requisite is addition of below instruction in cucumber.properties file

cucumber.publish.enabled=true

Cucumber.properties file should be present in src/test/resources.

Now, execute the Cucumber tests by using command — mvn test in command line.

Below image shows the Console message generated

If you follow the link, you’ll see your report rendered in glorious colour. Below is the image of such Cucumber Report. This report provide the information about

  1. No Of Test Scenarios Executed
  2. Passed vs Failed percentage
  3. When the tests are executed like 8 minutes ago or 15 hours ago
  4. Time taken to execute the Test Suite
  5. Window Version
  6. Java Version
  7. Cucumber-jvm Version
  8. Name of the feature file executed
  9. Test Scenario step execution – passed, failed, pending

The report is self destructed in 24 hours. It is mentioned as a warning at the top of the report.

To save the report for future use, click on the link – Keep your future reports forever. It will open a dialog box as shown below. You can create a Report Collection and the reports present in Report Collection are not auto-deleted.

Login to GitHub. A new page as shown below will appear. Create a collection by providing the name in the Name box and click the “Create new collection” button.

This page contains a token as shown in the image in the below screen. Mention this environment variable with token in cucumber.properties file which is present within src/test/resources.

When the tests will be executed, now the report will be saved under Cucumber Gradle Reports Collection.

Below is the image of the report which is saved under Cucumber Gradle Reports collection in GitHub.

If you have not added cucumber.properties to your project, then will get a screen as shown below.

Delete Report

The report can be deleted by clicking on Delete button on the report. Once you have clicked on Delete Report button, a dialog box as shown below is displayed. Once you click on Delete button present in the dialog box, the report is deleted permanently.

That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

SpringBoot Dependency Injection using Autowired

HOME

The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean Autowiring.

Now, let me explain this in simple language. Autowired provide us the object initialization.

Suppose, I have a Controller class called as UserController and a helper class called UserDaoService where I can write all the methods needed for UserController.

Now, I’ll annotate the helper class UserDaoService as @Component. I have created 3 methods in the helper class UserDaoService which are findAll(), save() and getOne().

Using findAll(), I will get data of all the users and in save() I will add the user in the list and findOne() will find a particular user from the list.

Objects in Spring Container is called Beans. When a class is annotated as @Component, it will create an object (bean) for that class. Here, in our example when we have annotated UserDaoService as @component , so at the time of application is in run mode it will create a bean for UserDaoService class in spring container.

In our controller class (UserController) there is dependency for Helper class (UserDaoService), so how our controller class beans know that there is helper class bean present in container. We need to told controller class bean to find out helper class bean and use it, so here @Autowired comes in picture. It will start to find bean for helper class and inject it into that variable so your variable in Initialized and ready to use.

Controller Class (UserResource)

@RestController  
public class UserController   
{  

   @Autowired  
   private UserDaoService service;
  
   @GetMapping("/users")  
   public List<User> retriveAllUsers()  
  {  
      return service.findAll();  
   }  
}  

Helper Class (UserDaoService)

import java.util.ArrayList;  
import java.util.Date;  
import java.util.List;  
import org.springframework.stereotype.Component; 
 
@Component  
public class UserDaoService   
{  

   public static int usersCount=5;  
   
    //creating an instance of ArrayList  
    private static List<User> users=new ArrayList<>();  

    //static block   
    static  
    {  

      //adding users to the list  
      users.add(new User(1, "John", new Date()));  
      users.add(new User(2, "Tom", new Date()));  
      users.add(new User(3, "Perry", new Date()));   
     }  

   //method that retrieve all users from the list  
   public List<User> findAll()  
   {  
      return users;  
   }  

    //method that add the user in the list   
    public User save(User user)  
    {  
      if(user.getId()==null)  
      {  
         //increments the user id  
         user.setId(++usersCount);  
      }  
     users.add(user);  
     return user;  
    }  

    //method that find a particular user from the list  
     public User findOne(int id)  
     {  
        for(User user:users)  
         {  
           if(user.getId()==id)  
           return user;  
         }  
     return null;  
   }  
} 

In the above example, UserDaoService is Autowired in UserController class using by property. Using Autowired, I have called method findAll().

   @Autowired  
   private UserDaoService service;

Use of @Autowired in Integration Testing of SpringBoot Application

Lets imagine a condition where different tests need to have a common test step. Suppose I have created 2 feature files where 1 feature file contain the tests related to valid Request/Response and another feature file create test scenarios related to various service errors. In both the cases, a test step where we have to send an access token to the requests is common. If I create this step in both StepDefinition files, it is duplicacy of code. To avoid this situation, we can create a Helper Class name as CommonStepDefinitions and declare it as @Componenet and @Autowired this helper class to specific StepDefinition class.

In the below example, I have created an access Token and I need to pass this access Token to the SpringBoot request to proceed further. I have @Autowired the CommonDefinition class to ValidRequestDefinitions and get the value of access token here and pass it to the request.

CommonStepDefinitions.class

@Component
@SpringBootTest
public class CommonStepDefinitions {

 @Given("^I generate an auth token to pass bearer token to request$")
    public String generateToken() throws JSONException {

	validatableResponse = given().auth().basic(username, password).param("grant_type", grant_type).when()
		.post(authUrl).then();

	JSONObject token = new JSONObject(validatableResponse.extract().asString());
	accessToken = token.get("access_token").toString();

	return accessToken;
  }

Main StepDefinition.class (ValidRequestDefinitions)

@SpringBootTest
public class ValidRequestDefinitions{

    private ValidatableResponse validatableResponse;
    private String bearerToken ;

    //Autowired on Property
    @Autowired
    CommonStepDefinitions helper;


    @When("^I send a valid request to the URL (.*)$")
    public void sendRequestToGenerateProcess(String endpoint) {

	bearerToken = helper.generateToken();

	validatableResponse = given().header("Authorization", "Bearer " + bearerToken).contentType(ContentType.JSON)
		.body(toString()).when().get(endpoint).then();

    }

That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

SpringBoot WireMock

HOME

What is WireMock?

WireMock is a library for stubbing and mocking web services. It constructs a HTTP server that act as an actual web service. When a WireMock server is in action, we have the option to set up expectations, call the service, and then verify the behavior of service. It allows us to:-

  • Capture the incoming HTTP requests and write assertions for the captured HTTP requests.
  • Configure the response returned by the HTTP API when it receives a specific request.
  • Identify the stubbed and/or captured HTTP requests by using request matching.
  • Configure request matchers by comparing the request URL, request method, request headers, cookies, and request body with the expected values.
  • Use WireMock as a library or run it as a standalone process.

Why do we need to Wiremock a SpringBoot Application

Suppose your SpringBoot Application calls an external application and this call to external service bear some cost. You can’t test the application without calling the external service, So in this case, we can use WireMock to mock the external application while testing the REST service that you are developing in SpringBoot.

Spring Cloud Contract WireMock

The Spring Cloud Contract WireMock modules allow us to use WireMock in a Spring Boot application.

To use WireMock in SpringBoot, add Maven dependency

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-wiremock</artifactId>
	<scope>test</scope>
</dependency>

To use WireMock’s fluent API add the following import:

import static com.github.tomakehurst.wiremock.client.WireMock.*;

We can use JUnit  @Rules  to start and stop the server. To do so, use the WireMockRule convenience class to obtain options instance, as the following example shows:

@Rule
    public WireMockRule wireMockRule = new WireMockRule(options().port(8081));

Wiremock runs as a stub server, and you can register stub behavior by using a Java API or by using static JSON declarations as part of your test.

Let us take the example of Student SpringBoot Application. The Response JSON of Student is shown below.

Creating a first WireMock mock service

Let us create a simple wiremock service with return status code as 200 and statsus message as “OK”.

@SpringBootTest
public class Wiremock_Example {

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(options().port(8081));

	@Test
	public void test() {
	 
       stubFor(get(urlPathEqualTo("/students"))
.willReturn(aResponse().withHeader("Content-Type", "application/json")
.withStatus(200).withStatusMessage("OK")));
	}
}
  1. options is imported from package static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
  2. @Rule & @Test are from junit
  3. WireMockRule is from com.github.tomakehurst.wiremock.junit.WireMockRule

The following code will configure a response with a status of 200 and status message of “OK” to be returned when the relative URL exactly matches /students (including query parameters). The body of the response will be “Tom” and Content-Type header will be sent with a value of application/json.

To create the stub described above via the JSON API, the following document can either be posted to http://<host&gt;:<port>/__admin/mappings or placed in a file with a .json extension under the mappings directory:

Dynamic port numbers

Wiremock has the facility to pick free HTTP and HTTPS ports in SpringBoot application, which is a good idea if we need to run the applications concurrently.

@ClassRule
public static WireMockClassRule wiremock = new WireMockClassRule(
			WireMockSpring.options().dynamicPort());

Below is an example which shows how you can mock an applictaion on dynamic ports. In the below example, the localhost port is dynamic here (57099).

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class Wiremock_Example {

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort());

	@Test
	public void test() {
         stubFor(get(urlPathEqualTo("/students")).willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(200).withStatusMessage("OK").withBody("Tom")));
	}
}

How to run and test Mock Service?

In the below example, I will use Rest Assured tests to validate the behaviour of Mock Service. First, I need to get the mock service up and running and then use it in a test.

@SpringBootTest
public class Wiremock_Example {

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(options().port(8089));

	public void setupMockService() {
		wireMockRule.stubFor(get(urlPathEqualTo("/students"))
.willReturn(aResponse().withHeader("Content-Type", "application/json")
.withStatus(200).withStatusMessage("OK")));
	}

	@Test
	public void positiveTest() {
		setupMockService();
   
        given()
       .when()
            .get("http://localhost:8089/students")
       .then()
            .assertThat().statusCode(200);
	}
}

In the below example, it is shown that the response content of a wiremock service can also be verified.

@SpringBootTest
public class Wiremock_Example {

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(options().port(8090));

	public void setupMockService() {

		wireMockRule.stubFor(get(urlPathEqualTo("/students"))
.willReturn(aResponse().withHeader("Content-Type", "application/json")
.withStatus(200).withStatusMessage("OK").withBody("Tom")));
	}

	@Test
	public void responseMessageTest() {

		setupMockService();
		 
         given()
        .when()
            .get("http://localhost:8090/students")
        .then()
           .assertThat().body(containsString("Tom"));
	}
}

How to read response body from a file?

To read the body content from a file, place the file under the  __files directory under src/test/resources when running from the JUnit rule.To make your stub use the file, use withBodyFile() on the response builder with the file’s path relative to __files.

public class Wiremock_Example {

	@Rule
	public WireMockRule wireMockRule = new WireMockRule(options().port(8085));

	public void setupMockService() {

		wireMockRule.stubFor(get(urlPathEqualTo("/students"))
.willReturn(aResponse().withHeader("Content-Type", "application/json")						.withStatus(200).withStatusMessage("OK").withBodyFile("Response.json")));
	}

	@Test
	public void responseFileTest() {

		setupMockService();

		given()
       .when()
           .get("http://localhost:8085/students").then()
       .assertThat()
           .body(containsString("John"));
	}
}

To read more about SpringBoot Wiremock, you can refer SpringBoot Wiremock website.

Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for DELETE Method to delete a Resource

HOME

In the previous tutorial, I explained about the Testing of SpringBoot PUT Method. In this tutorial, I will discuss about the Testing of DELETE method to delete a Resource in SpringBoot application.

To know how you can test a SpringBoot Application in BDD format using Serenity, refer the tutorial related to Serenity BDD with Cucumber for SpringBoot application.

The structure of project and various Java classes present in SpringBoot application and the dependencies need in POM.xml to test springboot framework are mentioned here.

Below is the code of Student Controller which exposes the services of DELETE method of Student resource.

@DeleteMapping("/students/{id}")

@DeleteMapping annotation maps HTTP DELETE requests onto specific handler methods. It is a composed annotation that acts as a shortcut for @RequestMapping(method=RequestMethod.DELETE) .

Code of StudentController.java for DELETE method is below

@DeleteMapping("/students/{id}")
	public void deleteStudent(@PathVariable long id) {
		studentRepository.deleteById(id);
	}

Here, we are deleting the student resource by Id.

Scenario 1- Below picture shows how we can execute a sucessful DELETE Request Method using Postman

Before Deleting a Student Resource with Id 1001

In the below image, it shows all the details of student with Id 1001 and with status code of 201 is returned.

Now, we delete a Student with Id 1001 and the status code returned is 200.

After deleting the resource, again send a request to get the details of student of id 1001 which returns 404 – Not Found status.

Above scenario can be tested in the below way.

Feature: Delete Student  Request

   @DeleteStudent
   Scenario: Send a valid Request to delete a student

    Given I send a request to the URL "/students/1001" to get the detail of user with Id 1001
    When I send a request to the URL "/students/1001" to delete user
    Then the response will return status of 200 
    And I resend the request to the URL "/students/1001" to get status of 404

Test Code to test above scenario (StepDefinition file)

@SpringBootTest(classes = SpringBoot2RestServiceApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class DeleteStudentsDefinition {

	private final static String BASE_URI = "http://localhost";

	@LocalServerPort
	private int port;

	private ValidatableResponse validatableResponse1, validatableResponse2, validatableResponse3;

	private void configureRestAssured() {

		RestAssured.baseURI = BASE_URI;
		RestAssured.port = port;
	}

	protected RequestSpecification getAnonymousRequest() throws NoSuchAlgorithmException {
		configureRestAssured();
		return given();
	}

	@Given("^I send a request to the URL \"([^\"]*)\" to get the detail of user with Id 1001$")
	public void getRequest(String endpoint) throws Throwable {

		validatableResponse1 = getAnonymousRequest().contentType(ContentType.JSON).body(toString()).when().get(endpoint)
				.then();
	}

	@When("^I send a request to the URL \"([^\"]*)\" to delete user$")
	public void iSendARequest(String endpoint) throws Throwable {

		validatableResponse2 = getAnonymousRequest().contentType(ContentType.JSON).when().delete(endpoint).then();
	}

	@Then("^the response will return status of (\\d+)$")
	public void extractResponseOfValidStudent(int status) throws NoSuchAlgorithmException {
		validatableResponse2.assertThat().statusCode(equalTo(status));
	}

	@And("^I resend the request to the URL \"([^\"]*)\" to get status of (\\d+)$")
	public void reverifyStudent(String endpoint, int status) throws NoSuchAlgorithmException {
		validatableResponse3 = getAnonymousRequest().contentType(ContentType.JSON).body(toString()).when().get(endpoint)
				.then();
		validatableResponse3.assertThat().statusCode(equalTo(status));

   }
}

We can test the negative scenario similarly. Send a request with invalid student id, then we will get 500 Internal Server Error.

The next tutorial explains about the Testing of SpringBoot Exception Handling.

Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for PUT Method to update a Resource

HOME

In the previous tutorial, I explained about the Testing of SpringBoot POST Method. In this tutorial, I will discuss about the Testing of PUT method to update a Resource in SpringBoot application.

To know how you can test a SpringBoot Application in BDD format using Serenity, refer the tutorial related to Serenity BDD with Cucumber for SpringBoot application.

The structure of project and various Java classes present in SpringBoot application and the dependencies need in POM.xml to test springboot framework are mentioned here.

Below is the code of Student Controller which exposes the services of PUT method of Student resource.

@PutMapping("/students/{id}")

PutMapping – It is Annotation for mapping HTTP PUT requests onto specific handler methods.

RequestBody – It maps body of the web request to the method parameter.

Code of StudentController.java for PUT method is below

@PutMapping("/students/{id}")
	public ResponseEntity<Object> updateStudent(@Valid @RequestBody Student student, @PathVariable long id) {

		Optional<Student> studentOptional = studentRepository.findById(id);
		if (!studentOptional.isPresent())
			return ResponseEntity.notFound().build();
		student.setId(id);
		studentRepository.save(student);
		return ResponseEntity.noContent().build();
	}

Here, we are checking if the student exists or not before updating the student. If the student does not exist, we return a not found status. Otherwise, we save the student details using studentRepository.save(student) method.

To test a PUT method of springboot application, you should use below code snippet to send a PUT request

Map<String, String> map = new HashMap<>();
   map.put("name", newName);
   map.put("passport", passport);

JSONObject newStudent = new JSONObject(map);
validatableResponse1 = getAnonymousRequest().contentType(ContentType.JSON).body(newStudent.toString()).when()
.put(endpoint).then();

Scenario 1- Below picture shows how we can execute a sucessful PUT Request Method using Postman

Before Updation

In the below image, details of all students with status code of 201 is returned.

Update Student – Here, I’m updating Student with Id 1001 from name Tom to Update and passport from AA234567 to AB000001

This is the image of updated Student of Id 1001

Above scenario can be tested in the below way.

Feature: Update Student Detail

   @UpdateStudent
   Scenario: Send a valid Request to update a student

    Given I send a request to the URL "/students" to get the detail of all users
    When I send a request to the URL "/students/1001" to update a user with name "Update" and passport as "AB000001"
    Then the response will return status of 204 for update student
    And I send a request to the URL "/students/1001" to get detail of updated student name as "Update"

Test Code to test above scenario (StepDefinition file)

@SpringBootTest(classes = SpringBoot2RestServiceApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class UpdateStudentDefinitions {

	private final static String BASE_URI = "http://localhost";

	@LocalServerPort
	private int port;

	private ValidatableResponse validatableResponse, validatableResponse1, validatableResponse2;

	private void configureRestAssured() {

		RestAssured.baseURI = BASE_URI;
		RestAssured.port = port;
		
	}

	protected RequestSpecification getAnonymousRequest() throws NoSuchAlgorithmException {
		configureRestAssured();
		return given();
	}

	@Given("^I send a request to the URL \"([^\"]*)\" to get the detail of all users$")
	public void getRequest(String endpoint) throws Throwable {

		validatableResponse = getAnonymousRequest().contentType(ContentType.JSON).body(toString()).when().get(endpoint)
				.then();
	}

	@When("^I send a request to the URL \"([^\"]*)\" to update a user with name \"([^\"]*)\" and passport as \"([^\"]*)\"$")
	public void updateRequest(String endpoint, String newName, String passport) throws Throwable {

		Map<String, String> map = new HashMap<>();
		map.put("name", newName);
		map.put("passport", passport);

		JSONObject newStudent = new JSONObject(map);

		validatableResponse1 = getAnonymousRequest().contentType(ContentType.JSON).body(newStudent.toString()).when()
				.put(endpoint).then();
	}

	@Then("^the response will return status of (\\d+) for update student$")
	public void extractResponse(int status) {

		validatableResponse1.assertThat().statusCode(equalTo(status));
	}

	@And("^I send a request to the URL \"([^\"]*)\" to get detail of updated student name as \"([^\"]*)\"$")
	public void extractUpdatedResponse(String endpoint, String newName) throws NoSuchAlgorithmException {

		validatableResponse2 = getAnonymousRequest().contentType(ContentType.JSON).when().get(endpoint).then();
		validatableResponse2.assertThat().body("name", equalTo(newName));
	}

Scenario 2- Below picture shows how we can execute a unsucessful PUT Request Method using Postman

In the above image, I am trying to update the name of invalid student id 1000, so the response returns the status of 404.

This can be tested by using above step definition.

To know about all the dependencies we need to add to pom.xml to run the SpringBoot Test, refer the tutorial about Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for GET Method.

The next tutorial explains about the Testing of DELETE method in SpringBoot Application.

Testing of SpringBoot Exception Handling

HOME

In the previous tutorial, I explained about the Testing of SpringBoot POST Method. In this tutorial, I will discuss the Testing of Exceptions in the SpringBoot application.

Response Statuses for Errors

The most commonly used error codes in SpringBoot Application are:-

  • 404 – RESOURCE NOT FOUND
  • 400 – BAD REQUEST
  • 401 – UNAUTHORIZED
  • 415 – UNSUPPORTED TYPE – Representation not supported for the resource
  • 500 – SERVER ERROR

Default Exception Handling with Spring Boot

Spring Boot provides a good default implementation for exception handling for RESTful Services.

This is the response when you try getting details of a non-existing student. You can see that the response status is 500 – Internal Server Error.

Customizing Exception Handling with Spring Boot

There are 2 most commonly used annotations used in Error Handling – @ExceptionHandler and @ControllerAdvice.

What is ExceptionHandler?

The @ExceptionHandler is an annotation used to handle the specific exceptions and send the custom responses to the client.

@ExceptionHandler(StudentNotFoundException.class)


What is ControllerAdvice?

A controller advice allows you to use exactly the same exception-handling techniques but apply them across the whole application, not just to an individual controller.

A combination of Spring and Spring Boot provides multiple options to customize responses for errors.

@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

You can specify the Response Status for a specific exception along with the definition of the Exception with the ‘@ResponseStatus’ annotation.

@ResponseStatus(HttpStatus.NOT_FOUND)

I have defined the StudentNotFoundExceptionclass. This Exception will be thrown by the controller when no resource i.e. Student to be returned in our case is found with HTTP Status of NOT_FOUND (404).

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class StudentNotFoundException extends RuntimeException {

	public StudentNotFoundException(String exception) {
		super(exception);
	}
}

Now the response will be 404 – Not Found

{
    "timestamp": "2021-02-22T15:56:59.494+00:00",
    "status": 404,
    "error": "Not Found",
    "trace": "StudentNotFoundException: id-100,
    "message": "id-100",
    "path": "/students/100"
}

Customizing Error Response Structure

The default error response provided by Spring Boot contains all the details that are typically needed.

However, you might want to create a framework-independent response structure for your organization. In that case, you can define a specific error response structure.

import java.util.Date;

public class ExceptionResponse {
	private Date timestamp;
	private String message;
	private String details;

	public ExceptionResponse(Date timestamp, String message, String details) {
		super();
		this.timestamp = timestamp;
		this.message = message;
		this.details = details;
	}

	public Date getTimestamp() {
		return timestamp;
	}

	public String getMessage() {
		return message;
	}

	public String getDetails() {
		return details;
	}
}

To use ExceptionResponse to return the error response, let’s define a ControllerAdvice as shown below.

@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

	@ExceptionHandler(StudentNotFoundException.class)
	public final ResponseEntity<Object> handleUserNotFoundException(StudentNotFoundException ex, WebRequest request) {
		ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
				request.getDescription(false));
		return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
	}

Scenario 1-  How to execute a Get Request Method with an Invalid URL using Postman

The above scenario can be tested in the below way.

Feature: Student Exception

   @InvalidURL
   Scenario: Send a valid Request to create a student

    Given I send a request to the invalid URL "/students/100" to get a student details
    Then the response will return status of 404 and message "id-100"

Test Code to test the above scenario (StepDefinition file)

@SpringBootTest(classes = SpringBootRestServiceApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class CustomizedErrorsDefinition {

	private final static String BASE_URI = "http://localhost";

	@LocalServerPort
	private int port;

	private ValidatableResponse validatableResponse;

	private void configureRestAssured() {

		RestAssured.baseURI = BASE_URI;
		RestAssured.port = port;
	}

	protected RequestSpecification getAnonymousRequest() throws NoSuchAlgorithmException {
		configureRestAssured();
		return given();
	}

	@Given("^I send a request to the invalid URL \"([^\"]*)\" to get a student details$")
	public void iSendARequest(String endpoint) throws Throwable {

		validatableResponse = getAnonymousRequest().contentType(ContentType.JSON).when().get(endpoint).then();
	}

	@Then("^the response will return status of (\\d+) and message \"([^\"]*)\"$")
	public void extractResponse(int status, String message) {		validatableResponse.assertThat().statusCode(equalTo(status)).body("message", equalTo(message));
	}
}

To know more about SpringBootTest, refer to the tutorial on Integration Testing of SpringBoot.

@SpringBootTest(classes = SpringBootRestServiceApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)

To know about all the dependencies we need to add to pom.xml to run the SpringBoot Test, refer to the tutorial about Testing of SpringBoot REST Application using Serenity BDD and Rest Assured for GET Method.

To know how you can test a SpringBoot Application in BDD format using Serenity, refer to the tutorial related to Serenity BDD with Cucumber for SpringBoot application.

The next tutorial explains the Testing of SpringBoot Validation for RESTful Services.