How to write a test suite with junit 5 for eclipse? - eclipse

I am trying to run by junit5 tests from a test suite. however Im getting an error
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.runner.RunWith;
import com.test.studentservice.controllers.StudentControllerTest2;
import com.test.studentservice.repo.StudentServiceRepoDataTest;
import com.test.studentservice.service.StudentServiceTest;
#RunWith(JUnitPlatform.class)
#SelectClasses({StudentControllerTest2.class, StudentServiceRepoDataTest.class, StudentServiceTest.class})
public class StudentServiceTestSuite {
}
This is the error I'm getting:
Thanks

You get this error, because in the JUnit launch configuration (Run > Run Configurations...) in the Test tab, you selected as Test runner the option JUnit 5 instead of JUnit 4.
#RunWith(JUnitPlatform.class) is used for the purpose to run JUnit 5 tests as JUnit 4 tests, in case a tool only supports JUnit 4 but not JUnit 5 (for details see this answer). But you don't need that since Eclipse supports JUnit 5 and should not use it since running it via the JUnit 4 API has some limitations.
Baeldung - A Guide to JUnit 5 - 7. Test Suites which you mentioned in a comment you are following here, is wrong, or at least misleading in this point. Instead of a JUnit Test Suite class, tag your tests and use them to include or to exclude tests (in the JUnit launch configuration, in the Test tab, hit the Configure... button for that).

From October-November 2021 jUnit5 support #Suite annotation:
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
#Suite
#SuiteDisplayName("Build Verification Test")
// Insert the class names in the order of execution
#SelectClasses({
FirstTest.class,
SecondTest.class
})
public class SuiteTest {
}
Pom:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.jupiter.version>5.8.0</junit.jupiter.version>
<junit.platform.version>1.8.0</junit.platform.version>
</properties>
...
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-api</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-commons</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite-engine</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
...

Related

Why is Eclipse trying to use JUnit5 when it should use JUnit4?

I'm just going through a tutorial which is a Maven project in Eclipse, and it should run some tests using JUnit4, so I have put this dependency in the POM:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
Still, trying to run the tests I get the following:
No tests found with testrunner 'JUnit5'
Why is Eclipse not using JUnit4 when this is the only dependency given in the project?
Because in the run configuration you have chosen JUnit 4 as Test Runner, Eclipse uses JUnit 4 instead of JUnit 5 to run this test.
Please note that even though Eclipse preselects the matching Test Runner for new run configurations, it does not change the Test Runner for existing run configurations.

Junit 5 tests don't launch in Eclipse due to NoClassDefFoundError: TestEngine

(There was no question for this problem in stackoverflow, so I decided to share question & solution here.)
I wanted to migrate my Spring Boot project from JUnit 4 to JUnit 5, so I added the new API as dependency and removed the old the ones:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
I wanted to do a full migration of my project, so I explicitly excluded everything from JUnit 4, and also did not include the junit-vintage-engine (as recommended in the official migration guide).
Then, I did the various changes to make the tests compile, like replacing #Before with #BeforeEach and organizing imports. All in all, this was pretty straightforward.
But running the tests in Eclipse caused some trouble:
First I got the message "Cannot find 'junit.framework.TestCase' on project build path. JUnit 3 tests can only be run if JUnit is on the build path." In the launch configuration dialog that popped up automatically, I was able to spot my mistake: I needed to select the 'Test runner' JUnit 5.
Still no success. Now I got the message "No tests found with test runner 'JUnit 5'. This was confusing, because I had used the correct JUnit 5 annotations on the test methods. Eclipse even confirmed this because the launch configuration 'Test method' search listed the test methods just fine.
After I while, I figured out that the test execution had printed a stack trace in the console:
java.lang.NoClassDefFoundError: org/junit/platform/engine/TestEngine
at org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry.loadTestEngines(ServiceLoaderTestEngineRegistry.java:35)
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:87)
at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader.<init>(JUnit5TestLoader.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:456)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createRawTestLoader(RemoteTestRunner.java:370)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.createLoader(RemoteTestRunner.java:365)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.defaultInit(RemoteTestRunner.java:309)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.init(RemoteTestRunner.java:224)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:208)
Caused by: java.lang.ClassNotFoundException: org.junit.platform.engine.TestEngine
at java.net.URLClassLoader.findClass(URLClassLoader.java:444)
at java.lang.ClassLoader.loadClass(ClassLoader.java:486)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:378)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
... 14 more
This pointed me to the root cause of the problem (see answer below)...
The problem was that I was missing the dependency to the engine library:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
Then, the tests run like a charm in Eclipse.
Migration blogs like https://dev.to/martinbelev/how-to-enable-junit-5-in-new-spring-boot-project-29a8 do mention this dependency, but I primarily worked with the JUnit 5 documentation, and somehow I must have overlooked this important piece of information there...

#SelectPackages not working with Maven CLI

I run mvn clean package and all other tests run except the suite test. I'm running both Junit 4 and 5 tests - #Rules tests run and #RegisterExtension/#ExtendWith tests also run. Not sure why the suite will not run - any ideas?
The code follows:
Test suite
#SelectPackages("com.company.platform.test.suite")
#IncludeClassNamePatterns({"^.*Suite$"})
public class SuiteTest {
}
Test being called by SuiteTest
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class TestingSuite {
#Test
public void add_2_plus_1(){
Assertions.assertThat(2 + 1).isEqualTo(3);
}
}
Pom
<junit-jupiter-engine.version>5.5.0</junit-jupiter-engine.version>
<junit-platform-runner.version>1.5.0</junit-platform-runner.version>
<!-- ellided -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter-engine.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit-jupiter-engine.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit-platform-runner.version}</version>
</dependency>
<!-- ellided -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
Maven, Java and OS details
mvn11 --version Sun Jul 21 14:43:24 EDT 2019
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T14:33:14-04:00)
Maven home: /usr/local/Cellar/maven/3.5.4/libexec
Java version: 11.0.1, vendor: Oracle Corporation, runtime: /Users/me/Downloads/jdk-11.0.1.jdk/Contents/Home
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.14.5", arch: "x86_64", family: "mac"
So I replicated your problem. When running
mvn clean test
i got the following output (among many others):
Juli 23, 2019 8:17:30 VORM. org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder buildRunner
WARNING: Ignoring test class using JUnitPlatform runner: com.example.project.SuiteTest
That's why I looked up the code of DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder and found the following comment:
/**
* Customization of {#link AnnotatedBuilder} that ignores classes annotated
* with {#code #RunWith(JUnitPlatform.class)} to avoid infinite recursion.
*/
private static class DefensiveAnnotatedBuilder extends AnnotatedBuilder {...}
This strongly suggests that suites using #RunWith(JUnitPlatform.class) are ignored when run through the platform mechanism. You might ask the junit 5 team if there is an explicit way to switch that security mechanism off but I'd guess there is none.
I suggest you extend the configuration of maven-surefire-plugin to mimic what you do in the suite:
#SelectPackages("com.company.platform.test.suite")
#IncludeClassNamePatterns({"^.*Suite$"})
can be translated into something like
<include>com.company.platform.test.suite/*Suite.java</include>
I didn't test it though.

Maven test finds but not executes tests

I have some test-classes under the folder src/test/java (some of these having name ending by *Test). Each class has some methods annotated with #Test
Running these tests with JUnit (on Eclipse, right click on the class, then run as, the JUnit Test) I have no problems. But I want to run these tests using mvn test.
The problem is that I obtain always this:
It seems that mvn finds the tests, but it doesn't execute them. Why?
Furthermore, it seems that also classes having a name that doesn't end with *Test are considered by Maven.
This is part of my pom.xml:
And this is part of my effective pom:
You are using a very outdated version of JUnit.
In JUnit 3.x, tests did not use annotations; the method names had to start with test*.
In JUnit 4.x, test methods had to be annotated with #Test, which is what you apparently have.
In your pom, you need to upgrade JUnit:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

Eclipse cannot resolve org.springframework.extensions.*

I should develope a java backed web script for alfresco but some libraries are missing on the classpath so most of the classes I like to use can not be resolved. I can build the project but Eclipse can not find the classes:
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
Where can I download the jar to add it to the classpath? I already searched and googled but I cannot find a download :/
if you are using maven ,add this to your pom.xml
<dependency>
<groupId>org.springframework.extensions.surf</groupId>
<artifactId>spring-webscripts</artifactId>
<version>1.0.0.M3</version>
</dependency>
<dependency>
<groupId>org.springframework.extensions.surf</groupId>
<artifactId>spring-webscripts-api</artifactId>
<version>1.0.0.M3</version>
</dependency>