VOOZH about

URL: https://www.geeksforgeeks.org/advance-java/how-to-test-an-abstract-class-with-junit/

⇱ How to Test an Abstract Class with JUnit? - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

How to Test an Abstract Class with JUnit?

Last Updated : 23 Jul, 2025

Testing abstract classes in Java can be challenging due to their incomplete nature. They cannot be instantiated directly. Abstract classes are often used as the blueprint for the other classes. They can include abstract methods, which lack implementations, as well as concrete methods that are fully implemented. Testing their behavior ensures that subclasses align with the specified contract.

In this article, we will learn different ways to test the abstract class using JUnit, with suitable examples, code snippets, and outputs of the Maven project.

Prerequisites:

  • Basic understanding of Java and JUnit.
  • Unit 5 for writing and executing tests.
  • Maven for building dependency management.
  • JDK and IntelliJ IDEA installed in your system.

Abstract Class

In Java, an abstract class is a type of class that cannot be directly instantiated and is designed to be inherited by other classes. It can contain both:

  • Abstract Methods: Methods declared without implementation, requiring subclasses to provide their concrete implementations.
  • Concrete Methods: Methods with defined implementations that can be directly used by subclasses.

Abstract classes are ideal for situations where you want to provide a common base with default behavior for multiple related classes while ensuring specific methods are implemented in subclasses.

Why Can’t We Instantiate Abstract Classes Directly?

Since abstract classes can have methods without implementation, creating an instance directly would lead to unimplemented behavior, which could result in runtime errors. Java prevents this by making abstract classes non-instantiable.

Purpose of Testing Abstract Classes

When working with the abstract class, we typically want to test:

  • Concrete Methods: Even though the class itself cannot be instantiated, it may contain the methods with logic that should be verified for correctness.
  • Contracts Defined by Abstract Methods: It ensures that when subclasses implement abstract methods.

For example, if the abstract class defines the template method pattern, it may provide the sequence of method calls with some methods abstract. Testing ensures that the intended sequence is respected when a subclass is created.

Project Implementation to Test an Abstract Class With JUnit

In this example, we will set up a project to test an abstract class Vehicle using JUnit. This will include file structure, code implementations, and explanations.

Step 1: Create a New Maven Project

In IntelliJ IDEA, create a new Maven project with the following settings:

  • Name: abstract-class-testing
  • Build System: Maven

Click on the Create button.

πŸ‘ Project Metadata

Project Structure

After the project creation done, set the file structure as shown in the below image:

πŸ‘ Project Folder Structure

Step 2: Add the JUnit dependencies to pom.xml

Open the pom.xml file and add the below JUnit dependencies.

Step 3: Define Vehicle.java (Abstract Class)

Create an abstract class Vehicle, which contains both an abstract and a concrete method.

Explantation:

  • Vehicle contains an abstract method getNumberOfWheels() and a concrete method start().
  • It has a name attribute and a constructor that initializes it.
  • getNumberOfWheels() must be implemented by any subclass.
  • start() is a concrete method that returns a message indicating that the vehicle has started.

Step 4: Define Car.java (Concrete Subclass)

Create a Car class that extends Vehicle and provides the implementation for getNumberOfWheels().

Explanation:

  • Car extends Vehicle and provides the implementation for getNumberOfWheels() that returns 4.
  • It inherits the start() method from the Vehicle class.
  • Car represents the vehicle with 4 wheels.

Step 5: Define Bike.java (Concrete Subclass)

Similarly, create a Bike class that extends Vehicle and implements getNumberOfWheels().

Explanation:

  • Bike extends Vehicle and provides the implementation for getNumberOfWheels() that returns 2.
  • It inherits the start() method from the Vehicle class.
  • Bike represents the vehicle with 2 wheels.

Step 6: Main Class (For Direct Testing)

The main class demonstrates the usage of Vehicle, Car, and Bike.

Step 7: VehicleTest.java (JUnit Test Class)

Create a JUnit test class to verify the behavior of the Vehicle abstract class and its subclasses.

Explanation:

testCarStartMethod()

  • Purpose: This test verifies that the start() method inherited by the Car class works as the expected. It checks whether the start() method returns the correct message for the vehicle name "Honda".
  • Expected Behavior: The method should be return the "Vehicle Honda started" when called on the Car instance.

testBikeStartMethod()

  • Purpose: This test checks the behavior of the start() method when called on the Bike instance. It ensures that start() method works consistently across the different subclasses.
  • Expected Behavior: The method should be return "Vehicle Yamaha started" when called on the Bike instance.

testCarNumberOfWheels()

  • Purpose: This test ensures that the Car class correctly implements the getNumberOfWheels() method and returning the expected value of 4.
  • Expected Behavior: The method should return 4, as the cars typically have four wheels.

testBikeNumberOfWheels()

  • Purpose: This test verifies that the Bike class implements the getNumberOfWheels() method correctly and returns the value 2.
  • Expected Behavior: The method should return 2, as the bikes generally have two wheels.

testAnonymousClassImplementation()

  • Purpose: This test uses the anonymous class to directly implement the abstract Vehicle class without creating the formal subclass. It tests both the start() and getNumberOfWheels() methods.
  • Expected Behavior:
    • The start() method should return "Vehicle Anonymous started", demonstrating that the anonymous class inherits and uses the abstract class's concrete method.
    • The getNumberOfWheels() method should return 3 and simulating the tricycle with three wheels.

Step 8: Run the Application

After the project completed, run the project, and it will display the below output in console.

πŸ‘ Output


Step 9: Testing the Application

Now, we will run the test suites using the below maven command:

mvn test

We should see the following test results:

πŸ‘ Test Results

This output confirms that all the tests passed successfully, verifying that both the abstract class Vehicle and its subclasses are functioning as expected.

Explanation of Test Output

  • Tests Run: 5 tests were executed, one for each of the test methods defined in the VehicleTest.
  • Failures and Errors: All tests are passed successfully (Failures: 0, Errors: 0), meaning that all the expected behavior was correctly implemented and verified.
  • Time Elapsed: The total time taken to run all the tests is minimal, it is indicating that the test suite runs efficiently.

Significance of the Output

  1. No Failures: The output confirms that the vehicle abstract class and its subclasses (Car and Bike) behaves as expected. The start() method works correctly for all the classes, and the getNumberOfWheels() method returns the right values for the each subclass.
  2. Anonymous Class Testing: The successful execution of the anonymous class test shows that we can directly the test abstract methods by creating the temporary implementations, providing flexibility in the testing.
Comment
Article Tags:
Article Tags:

Explore