How are Java POJO tests getting executed without a test framework?

73 Views Asked by At

I am working on a Java 11 application, and I have the following POJO test.

public class HelloWorldTest {

    public void testGetHello() {

        assert("Hello World!".equals(HelloWorld.getHello()));
    }
}

Below is the pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>guru.springframework</groupId>
    <artifactId>helloworld</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
   </dependencies>
</project>

When I run "mvn test" in IntelliJ Terminal, the HelloWorldTest gets picked up and executed.

What is happening under the hood? I understand that as I am using Maven, Surefire plugin gets pulled it, but what test runner is Surefire plugin using to pick up and execute the HelloWorldTest?

1

There are 1 best solutions below

1
Honza Zidek On

Everything in the POJO tests is based on the Java reflection.

https://maven.apache.org/surefire/maven-surefire-plugin/examples/pojo-test.html

POJO tests look very much like JUnit or TestNG tests, though they do not require dependencies on these artifacts. A test class should be named **/*Test and should contain test* methods which will each be executed by Surefire.

Validating assertions can be done using the JDK 1.4 assert keyword.

Fixtures can be setup before and after each test* method by implementing a set-up and a tear-down methods. These methods must match the following signatures to be recognized and executed before and after each test method:
public void setUp();
public void tearDown();

Surefire uses test providers, each of them is an implementation of Maven Surefire Provider API. The provider implementations are found using the standard Java ServiceLoader mechanism:

private Set<String> getManuallyConfiguredProviders() {
    ...
    return serviceLoader.lookup(SurefireProvider.class, cl);
    ...
}

https://maven.apache.org/surefire/maven-surefire-plugin/usage.html

Which providers are available is controlled simply by the inclusion of the appropriate dependencies (JUnit4, JUnit5 and TestNG).

https://maven.apache.org/surefire/maven-surefire-plugin/examples/providers.html

You can also specify multiple providers as dependencies, and they will all be run and produce a common report. This may be especially handy with external providers, since there are few use cases for combining the included providers.

If you download the Surefire source code, you can see that there are some "well-known surefire providers":

protected List<ProviderInfo> createProviders(TestClassPath testClasspath) throws MojoExecutionException {
    Artifact junitDepArtifact = getJunitDepArtifact();
    return providerDetector.resolve(
            new DynamicProviderInfo(null),
            new JUnitPlatformProviderInfo(getJUnitPlatformRunnerArtifact(), getJUnit5Artifact(), testClasspath),
            new TestNgProviderInfo(getTestNgArtifact()),
            new JUnitCoreProviderInfo(getJunitArtifact(), junitDepArtifact),
            new JUnit4ProviderInfo(getJunitArtifact(), junitDepArtifact),
            new JUnit3ProviderInfo());
    }

Since the JUnit3 tests were based purely on reflection, it is the JUnit3Provider which runs the POJO tests, because it uses exactly the same method to identify the tests within the source code.

public JUnit3Provider(ProviderParameters booterParameters) {
    ...
    testChecker = new PojoAndJUnit3Checker(jUnit3TestChecker);
}

Your question about which test runner is used does not make sense in the case of the POJO tests, as test runner is a term from JUnit and TestNG, and not from Surefire.