Skip to main content

Maven Tests

Maven Test

When you execute mvn test it will compile and test the source code that's underneath the source code folder!

Maven Test allows integration with JUnit, TestNG, and POJO. We will go over JUnit because that's what we use most of the time.

JUnit

Writing them are still the same, however, integrating it with behavioral driven testing framework like Cucumber will be different I will go over the differences for using cucumber with JUnit 4 and JUnit 5 (Mainly in the annotation that is used to specify the glue and feature files)

When you write your unit tests using JUnit you want to structure your file directory like the following:

src
├── main
│   ├── java
│   │   └── test
│   │       └── App.java
│   └── resources
│       └── application.properties
└── test
    ├── java
    │   └── test
    │       └── AppTest.java
    └── resources
        └── test.json

Your main source code directory will contain two different directories.

  • The main directory contain the Java source code for your application as well as any resources that your application uses
  • The test directory contain the Java source code used for testing. This is where you will be writing your unit test for your applications

When you run mvn test it will compile the source code from the src directory and execute the proper unit test using the JUnit framework.

Dependency needed for JUnit 5
<dependencies>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.1</version>
    <scope>test</scope>
  </dependency>
</dependencies>

Test Class

A test class is a class that will be used by Maven to carry out the testing.

A test class contains methods that will be tested by Maven. Maven use a pattern to check whether a class is a test class or name, the list of pattern used by Maven to determine if a class is a test class is of the following:

**/Test*.java           
**/*Test.java           
**/*Tests.java          
**/*TestCase.java       

Test Runner Class

This applies to JUnit 4 test. JUnit 5 has a new API and @RunWith is no longer needed.

A test runner in JUnit is just a simple class that implements the Describable interface. The interface just have two abstract methods to implement:

public abstract class Runner implements Describable {
  public abstract Description getDescription();
  public abstract void run(RunNotifier notifier);
}
  1. getDescription: Is used to return a description containing the information about the test, this is used by different tools such as those from IDE
  2. run: This is used to actually run the test class or test suite

You can implement your own test runner to do custom logic for running tests, for example you can print out silly messages just before each test is run.

A simple test runner class implementation can be found below: All it does is before it runs the test class is it prints the message "MyRunner <TestClass>"

//src/main/java/MinimalRunner
package com.codingninjas.testrunner;


import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.Test;
import java.lang.reflect.Method;



public class MinimalRunner extends Runner {


    private Class testClass;
    public MinimalRunner(Class testClass) {
        super();
        this.testClass = testClass;
    }
    
    //getDescription method inherited from Describable
    @Override
    public Description getDescription() {
        return Description
          .createTestDescription(testClass, "My runner description");
    }
    
    //our run implementation 
    @Override
    public void run(RunNotifier notifier) {
        System.out.println("running the tests from MyRunner: " + testClass);
        try {
            Object testObject = testClass.newInstance();
            for (Method method : testClass.getMethods()) {
                if (method.isAnnotationPresent(Test.class)) {
                    notifier.fireTestStarted(Description
                      .createTestDescription(testClass, method.getName()));
                    method.invoke(testObject);
                    notifier.fireTestFinished(Description
                      .createTestDescription(testClass, method.getName()));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}