Encapsulation in Java is a process of wrapping the data and code in a single unit. The whole idea behind encapsulation is to hide the implementation details from users. If a data member is private it means it can only be accessed within the same class. No outside class can access private data member (variable) of other class. It is one of the four important OOPs concept.
To achieve encapsulation in Java −
Declare the variables of a class as private.
Provide public setter and getter methods to modify and view the variables values.
The get method returns the variable value, and the set method sets the value.
Syntax of get method – method name starts with get followed by the variable name where first letter is capital.
Syntax of set method – method name starts with set followed by the variable name where first letter is capital.
Below is an example of encapsulation with two variables and their getter and setter method.
public class EncapsulationDemo {
// private variables
private String name;
private int age;
// getter method for age
public int getAge() {
return age;
}
// setter method for age
public void setAge(int setAge) {
this.age = setAge;
}
// getter method for name
public String getName() {
return name;
}
// setter method for name
public void setName(String newName) {
this.name = newName;
}
}
The variables of the EncapsulationDemo class can be accessed using the following program −
public class EncapsulationTest {
public static void main(String[] args) {
//creating instance of the encapsulated class
EncapsulationDemo encap = new EncapsulationDemo();
//setting value in the age member
encap.setAge(25);
//setting value in the name member
encap.setName("Terry");
//getting value of the age and name member
System.out.print("Name : " + encap.getName() + " and Age :" + encap.getAge());
}
}
Output
Name : Terry and Age :25
The encapsulate class is easy to test. So, it is better for unit testing.
The standard IDE’s are providing the facility to generate the getters and setters. So, it is easy and fast to create an encapsulated class in Java.
In this tutorial, we will discuss Inheritance and types of Inheritance in Java.
What is Interitance?
Inheritance can be defined as the process where one class acquires the properties (methods and fields) of another class.
The class which inherits the properties of other is known as subclass (derived class, child class) and the class whose properties are inherited is known as superclass (base class, parent class).
Inheritance is applicable for public and protected members only. Private members can’t be inherited.
Inheritance represents the IS-A relationship which is also known as a parent-child relationship.
Inheritance supports the concept of “reusability”, i.e. when we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class. By doing this, we are reusing the fields and methods of the existing class.
The keyword used for inheritance is extends.
Syntax
class derived-class extends base class
{
//methods and variables
}
Below is an example of Inheritance. In the below example, ParentCalculation is the Base class (parent class) and has a method addition. ChildCaclculation is the derived class (child class) which has extends base class ParentCalculation. When an object of ChildCaclculation class is created, a copy of all methods and fields of the superclass acquire memory in this object. That is why by using the object of the subclass we can also access the members of a superclass.
Base Class
public class ParentCalculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("The sum of the given numbers:" + z);
}
}
Derived Class
public class ChildCaclculation extends ParentCalculation {
int c;
public void multiplication(int a, int b) {
c = a * b;
System.out.println("The multiplication of the given numbers:" + c);
}
public static void main(String[] args) {
ChildCaclculation cal = new ChildCaclculation();
cal.addition(10, 14);
cal.multiplication(5, 6);
}
}
Output
The sum of the given numbers:24
The multiplication of the given numbers:30
Types of Inheritance in Java
Below are the different types of inheritance available in Java.
1. Single Inheritance
In single inheritance, subclass (derived) inherit the features of superclass (base). In the image below, class A serves as a base class for the derived class B.
Base Class
public class Employee {
String name = "Tom";
int emp_no = 12001;
public void displayEmployee() {
System.out.println("Base Class");
System.out.println("Name :" + name);
System.out.println("Emp_No :" + emp_no);
}
}
Derived Class
package JavaDemo.Inheritance;
public class Department extends Employee {
String deptName = "IT Division";
public void displayDept() {
System.out.println("Derived Class");
System.out.println("Department Name :" + deptName);
}
public static void main(String[] args) {
Department dept = new Department();
// Derived method
dept.displayDept();
// Base Method
dept.displayEmployee();
}
}
Output
Derived Class
Department Name :IT Division
Base Class
Name :Tom
Emp_No :12001
2. Multilevel Inheritance
In this, derived class extends an base class as well as the derived class act as a base class for another derived class. In the below example, Employee is Base class, Department is intermediate derived class and SubDivision is derived class.
Base Class
package JavaDemo.Inheritance;
public class Employee {
String name = "Tom";
int emp_no = 12001;
public void displayEmployee() {
System.out.println("Base Class");
System.out.println("Name :" + name);
System.out.println("Emp_No :" + emp_no);
}
}
Intermediate Derived Class
package JavaDemo.Inheritance;
public class Department extends Employee {
String deptName = "IT Division";
public void displayDept() {
System.out.println("Intermediate Derived Class");
System.out.println("Department Name :" + deptName);
}
public static void main(String[] args) {
Department dept = new Department();
// Intermediate Derived method
dept.displayDept();
// Base Method
dept.displayEmployee();
}
}
Derived Class
package JavaDemo.Inheritance;
public class SubDivision extends Department {
String sub_division = "Production Support";
public void displaySubDivision() {
System.out.println("Derived Class");
System.out.println("SubDivision Name :" + sub_division);
}
public static void main(String[] args) {
SubDivision div = new SubDivision();
// Derived method
div.displaySubDivision();
// Intermediate Derived method
div.displayDept();
// Base Method
div.displayEmployee();
}
}
Output
Derived Class
SubDivision Name :Production Support
Intermediate Derived Class
Department Name :IT Division
Base Class
Name :Tom
Emp_No :12001
3. Hierarchical Inheritance
In Hierarchical Inheritance, one class serves as a superclass (base class) for more than one subclasses.
In the below example, Employee is the base class. Department and Salary are the derived classes.
Base Class
package JavaDemo.Inheritance;
public class Employee {
String name = "Tom";
int emp_no = 12001;
public void displayEmployee() {
System.out.println("Base Class");
System.out.println("Name :" + name);
System.out.println("Emp_No :" + emp_no);
}
}
Derived Class1
public class Department extends Employee {
String deptName = "IT Division";
public void displayDept() {
System.out.println("Derived Class 1");
System.out.println("Department Name :" + deptName);
}
public static void main(String[] args) {
Department dept = new Department();
// Derived method
dept.displayDept();
// Base Method
dept.displayEmployee();
}
}
Derived Class2
package JavaDemo.Inheritance;
public class Salary extends Employee {
float Salary = 65000;
public void displaySalary() {
System.out.println("Derived Class 2");
System.out.println("Salary :" + Salary);
}
public static void main(String[] args) {
Salary sal = new Salary();
sal.displaySalary();
sal.displayEmployee();
System.out.println("=========================");
Department dept = new Department();
dept.displayDept();
dept.displayEmployee();
}
}
Output
Derived Class 2
Salary :65000.0
Base Class
Name :Tom
Emp_No :12001
=========================
Derived Class 1
Department Name :IT Division
Base Class
Name :Tom
Emp_No :12001
4. Multiple Inheritance
In Multiple inheritances, one class can have more than one superclass and inherit features from all parent classes. Java does not support multiple inheritances with classes. We can achieve multiple inheritances only through Interfaces.
5. Hybrid Inheritance
It is a combination of single and multiple inheritance. As Java doesn’t support multiple inheritances with classes, hybrid inheritance is also not possible with classes. In java, we can achieve hybrid inheritance only through Interfaces.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
In the previous tutorial, I have explained about thecontrol 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");
}
}
The output of the above program is
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");
}
}
The output of the above program is
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");
}
}
The output of the above program is
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");
}
}
The output of the above program is
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");
}
}
The output of the above program is
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");
}
}
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
Exceptions in Java are events that disrupt the normal flow of the program’s instructions during runtime. When an exceptional event occurs, an exception object is created, which the runtime system then throws. This exception object contains information about the error, including its type and the state of the program when the error occurred.
Category of Exceptions
Java defines two categories of exceptions – Built-in Exceptions and User-Defined Exception.
Built-in Exceptions
These exceptions are available in Java libraries. There are various types of exceptions which are suitable to specific type of exception situations. Built-in Exceptions are divided into Checked and Unchecked Exceptions.
Checked Exceptions
These are exceptions that are checked at compile-time.
They must be either handled using a try-catch block or declared in the method signature using the `throws` keyword.
Examples include IOException, SQLException, and FileNotFoundException.
UnChecked Exceptions
These are exceptions that are not checked at compile-time but are instead checked at runtime.
Unchecked exceptions are subclasses of RuntimeException. They do not need to be declared or handled explicitly.
Examples include NullPointerException, ArrayIndexOutOfBoundsException, and ArithmeticException.
User-defined or Custom Exceptions
There are several conditions where built-in exceptions in Java is unable to handle certain situations. In such cases, user can create a custom or user defined exception.
In this tutorial, I’ll explain about built-in exceptions.
Types of Exceptions
1. ArithmeticException
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");
}
}
}
}
The output of the above program is
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");
}
}
}
}
The output of the above program is
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");
}
}
}
}
The output of the above program is
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");
}
}
}
}
The output of the above program is
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");
}
}
}
The output of the above program is
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");
}
}
}
The output of the above program is
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");
}
}
}
The output of the above program is
8. IOException
It is thrown when an input-output operation failed or interrupted.
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");
}
}
}
The output of the above program is
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.
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
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 clean test in command line.
Below image shows the Console message generated
If you follow the link, you’ll see your report rendered in glorious color. Below is the image of such Cucumber Report. This report provide the information about
No Of Test Scenarios Executed
Passed vs Failed percentage
When the tests are executed like 8 minutes ago or 15 hours ago
Time taken to execute the Test Suite
Window Version
Java Version
Cucumber-jvm Version
Name of the feature file executed
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!!
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!!
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
We can use JUnit @Rules to start and stop the server. To do so, use the WireMockRule convenience class to obtain optionsinstance, 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")));
}
}
options is imported from package static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
@Rule & @Test are from junit
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 tohttp://<host>:<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.
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.
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.