'Junit 5 @SpringBootTest executable jar
I am trying to create an executable jar with my test. I cannot use maven to run the tests so I am trying to create a jer that will execute them.
I have a jar with all the test's and with all dependencies. But, when I try to run:
java -jar target/tests-0.0.1-SNAPSHOT-spring-boot.jar
I am getting -
Exception in thread "main" java.lang.ClassNotFoundException: com.xxx.xx.tests.framework.SDAutomation
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
pom.xml include the following to create the jar:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>spring-boot</classifier>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals> <goal>single</goal> </goals>
<configuration>
<archive>
<manifest>
<mainClass>com.xxx.xx.tests.framework.SDAutomation</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
Any help will be great.
Edit 1: found a seleution by creating a main with LauncherFactory for example:
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(
selectClass(SDAutomation.class)
)
.build();
Launcher launcher = LauncherFactory.create();
// Register a listener of your choice
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
TestExecutionSummary summary = listener.getSummary();
taken from juint doc
Solution 1:[1]
Spring boot works with a Jar which is not a Jar really. When you use spring-boot-maven- plugin
- you instruct maven to prepare such a spring boot jar. I suggest to open this jar with some kind of WinRar/WinZip application and see what's inside actually.
So, if you have a spring boot jar and try to run it as a spring boot application it will load the main class and run it.
This main class should run programmatically all the automation tests and If I understand correctly this is exactly what SDAutomation
is supposed to do.
But then you use maven assembly plugin and try to edit its manifest and specify the main plugin - do not do it. Instead specify the main class in a spring boot plugin. So this is clearly a mistake
The third step is even more confusing - you create a test jar, that's cool, but where do you use it?
So how to really solve this issue:
- You should decide whether you want to use spring boot at all to run tests. Frankly I don't see a point of doing so - you could create a fat jar of all the dependencies and run tests from there. Unless these tests are not designed as
@SpringBootTest
which is also doesn't make sense for automation tests, here is why:
Spring Boot Test is an integration framework as opposed to automation tests which are usually cover the end to end flow. Automation tests run in the different JVM as the application as opposed to spring boot tests that provide a lot of convenience features for loading the application context of the real application inside of the test (or a part of application context). Automation tests should not load any production code at all... Probably if you could elaborate more on the purpose of the automation test suite - I could provide more information.
Even if you run the spring boot application, it should not be the same spring boot application that runs the production code. Probably you should create another maven module, provide a dependency on the artifact with a test classifier and in the main method use console application (again, no web server in this case is required) to run the test suite.
Last but not the least. Surefire/failsafe plugins of maven besides actually running the tests, also produce reports that can be integrated with a CI tool. Since you won't have any maven / surefire there (from your comment) you won't be able to benefit from these reports.
Solution 2:[2]
Below are steps ->
Step 1: Add the below plugins to your POM file -
<build>
<finalName>dockerized-springfield</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/java/com/automation/framework/gui/testng.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<classpathDependencyExcludes>
<classpathDependencyExclude>com.vaadin.external.google:android-json</classpathDependencyExclude>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>
Step 2: Run mvn commands to create jars
mvn package -DskipTests
This will create 3 jars files inside your target folder
- application.jar [Springboot jar which contains code inside "main" folders along with the dependencies.]
- application.jar.original [Jar which ONLY contains code inside "main" folders]
- application-tests.jar [Jar which contains code inside the "test" folder.]
We only need the 2nd and 3rd jar files. You may delete the first file. Now rename the second file and remove the ".original" from its file name. Let's say mainapplication.jar
We will also need the libs folder which contains jar files for respective dependencies mentioned in the POM file.
Step 3: Run your jar files.
java -cp mainapplication.jar:application-tests.jar:libs/* org.testng.TestNG testng.xml
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mark Bramnik |
Solution 2 | Uchiha Suryajit |