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
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.
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
Related
I am using Cucumber framework for mobile app testing. In pom.xml, I have given this below plugin to run TestClass.java - which has code for uploading the latest APK version of the app. Main method is present inside this TestClass. I need this to run before the actual test execution. So I have used exec plugin. I'm getting this error if I am running with pom.xml --> mvn clean test. ClassNotFoundExpection is always thrown with pom.xml, but the individual class runs perfectly.
pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>installAPK</id>
<phase>generate-test-sources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>org.com.package1.TestClass</mainClass>
</configuration>
</plugin>
Console error:
java.lang.ClassNotFoundException: org.com.package1.TestClass
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:246)
at java.lang.Thread.run(Thread.java:748)
I also tried changing the phase after test-compile. Still i am getting the same error. Someone pls help.
According to the exec-maven-plugin documentation, the default dependency scope for the execution is runtime. Please change it to test with the following configuration if the TestClass is part of the test sources.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
...
</executions>
<configuration>
...
<classpathScope>test</classpathScope>
</configuration>
</plugin>
I am trying to run integration testing on my maven project inside a docker container. I am using dockerfile-maven plugin to move jar file inside my docker container and maven-failsafe-plugin to initiate my integration testing. But somehow integration testing starts before docker being built. Also it doesn't call my test functions.
Here is my pom.xml snippet.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
<configuration>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.7</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>rohitbarnwal7/presto_him</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>plugin-${project.version}-jar-with-dependencies.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
Update: With above configuration, integration test class are being called but none of the test is actually executed.
Any help will be highly appreciated. Thanks.
You need to bind the building of the image to a maven phase that runs before integration test.
As documented in Bind Docker commands to Maven phases, you can bind building the docker image to a specific maven phase as such:
build-image
compile
package
In this case, building the image will take place at the maven package phase which will run before integration-test phase
I am trying to use the jsonschema2pojo plugin for generating POJOs based on both schema and json sourceTypes. The configurations are specified per execution. But every time the plugin is reporting "One of sourceDirectory or sourcePaths must be provided". I am able to run it when the configuration is provided at the plugin level ( global ). But then I can only specify one sourceType.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>0.5.1</version>
<executions>
<execution>
<id>generate-schema</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>false</generateBuilders>
<initializeCollections>true</initializeCollections>
<refFragmentPathDelimiters>#/</refFragmentPathDelimiters>
<sourceType>jsonschema</sourceType>
<targetPackage>com.company.app.integration.sabre.stub.rest</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/schema</sourceDirectory>
</configuration>
</execution>
<execution>
<id>generate-json</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>false</generateBuilders>
<initializeCollections>true</initializeCollections>
<refFragmentPathDelimiters>#/</refFragmentPathDelimiters>
<sourceType>json</sourceType>
<targetPackage>com.company.app.integration.sabre.stub.rest</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/json</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Is there any way to have the plugin use the configuration at execution level per goal ?
Plugin version: 0.5.1
tl;dr
When running the 'compile' from Maven projects lifecycle, the plugin is considering the configuration from execution and is working as expected.
I am using Intellij and was trying to generate the pojo from Plugins -> jsonschema2pojo -> jsonschema2pojo:generate under 'Maven Projects' window. This was giving the above error and was not taking the configuration per execution.
When I run compile from the Maven Lifecycle, it is picking the configuration in the execution and is generating the files as specified.
I am not yet sure if this is a issue with the plugin or maven or if its a issue at all !!
Try moving your configuration out to the plugin level and using the parent folder (${baseDir}/src/main/resources) as the sourceDirectory.
Here's an old bug report describing the same thing:
https://github.com/joelittlejohn/jsonschema2pojo/issues/145
I have an application composed of multiple maven war projects.
I have another maven project that runs JUnit integration tests against the manually-started tomcat-deployed multi-war application using org.springframework.web.client.RestTemplate calls.
However, I'd like my integration test project to actually start my multi-war application (once for the duration of the entire suite) before it runs my tests...in spring-boot!
From my integration test project, I'd like to be able to run all the war projects together as a spring-boot application, each with their own contextPaths (e.g. localhost:8080/a for project 'a', localhost:8080/b for project 'b', etc. ), and without changing the original war projects (that are not (yet) spring-boot aware). If I can't make these projects run from my integration test project in spring-boot without changing them then I'd at least like to minimize the use of spring-boot dependencies and configuration in packaged war files...as much as possible.
I was able to get my integration test project to depend on a single war project, start it up and run tests against it...but I was unsuccessful getting two war projects running together in spring-boot under separate contextPaths.
Any suggestions would be welcome!
Here are some of the resources I've been using to put this together:
(Spring-boot documentation) http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
(Blog post touching on starting spring app once for test suite) http://www.nurkiewicz.com/2010/12/speeding-up-spring-integration-tests.html
(Suggestions for including war files as dependencies in a integration test project pom) http://eureka.ykyuen.info/2009/10/30/maven-dependency-on-jarwar-package/
As per Andy's suggestion, I went with the Tomcat7 Maven Plugin and it worked just fine. The Jetty Maven Plugin was another option (and better documented IMO) although I couldn't find a way to avoid having to provide a "path" to my WAR files. The Tomcat7 Maven Plugin, let me load up my WARs from my local .m2 repository. I should also say that the following links were helpful as well...
http://cupofjava.de/blog/2013/02/05/integration-tests-with-maven-and-tomcat/
https://stackoverflow.com/a/16936585/1098564
Here's part of my integration test project pom...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.17</version>
<configuration>
<includes>
<include>**/*Test*</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<webapps>
<webapp>
<groupId>com.mycompany</groupId>
<artifactId>app1</artifactId>
<version>${project.version}</version>
<type>war</type>
<asWebapp>true</asWebapp>
</webapp>
<webapp>
<groupId>com.mycompany</groupId>
<artifactId>app2</artifactId>
<version>${project.version}</version>
<type>war</type>
<asWebapp>true</asWebapp>
</webapp>
</webapps>
</configuration>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war</goal>
</goals>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Some unit tests in my application are related to finding and manipulating certain files resources that are part of the application itself.
I need these tests to be executed in the real production setting of the application, where it is deployed as a JAR file, not as an exploded directory.
How could I instruct Maven to execute my unit tests considering as the classpath the project generated jar file (and any other declared library dependencies) instead of the compiled classes in the file system as it does by default?.
In other words, right now the classpath for my unit tests is set to: /$PROJECTPATH/target/classes/.
Instead, I would like this classpath to be set to: /$PROJECTPATH/target/myjarfile.jar.
I have tried manually adding and removing dependency classes, as explained here:
http://maven.apache.org/plugins/maven-surefire-plugin/examples/configuring-classpath.html
,but until now it is not working.
My current project POM looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.mygroupid</groupId>
<artifactId>myartifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>process-resources</phase>
<!-- <phase>package</phase> -->
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.3</version>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExclude>
${project.build.outputDirectory}
</classpathDependencyExclude>
</classpathDependencyExcludes>
<additionalClasspathElements>
<additionalClasspathElement>
${project.build.directory}/${project.build.finalName}.${project.packaging}
</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
</project>
Thanks in advance for any help!.
The standard unit tests executed as part of the test lifecycle phase cannot see the project JAR because the test phase is executed before the package phase, so your tests are run before Maven generates the JAR. See this page for a list of lifecycle phases and their order.
What you want it to run your tests as integration tests, which execute in the integration-test phase.
There are a number of tutorials for setting up Maven to run integration tests. Here and here are a couple of starters. The failsafe plugin is typically used for executing integration tests.
I can't recall exactly if integration tests use target/classes or your project's JAR file in the classpath. But if it doesn't you could always create another Maven project, add your tests in there and add the main project as a dependency to this integration test project. In some cases this can be preferable to using the integration test phase in the main project if it is not just a standard Java library, for example if you are writing an annotation processor.