At first I placed my Mockup classes and web config in the
src/main
folder from my maven project and added the jetty plugin to my pom.xml
file. This way I was able to start my REST MockupService simply by typing mvn jetty:run
on the console. After starting the service I was able to execute my test classes directly from Eclipse. But this approach did not satisfy me at all, because now I had lots of files in my main project folder, which would not be needed once I build and deploy my STS extensions to another STS installation. Somehow I needed to move all files (Mockup Service, Spring beans.xml, web.xml, etc.) to the test project folder.In this post I'll explain how to setup you maven pom file so that you can use Jetty in your integration test phase if your packaging goal is not a war file but a simple jar file instead and all your web configuration and classes are located in your test folder.
There are two Blogs which I found very helpful to get my use case up and running:
- Run Jetty in the Maven life-cycle
- End-to-End Client-Server Integration Testing with Maven – Project Setup
src/main/webapp
folder to src/test/webapp
as well as src/main/resources
to src/test/resources
since I needed these files only for testing. The same was true for some of my classes in src/main/java
which I moved to src/test/java
. Now my src/main/
folder only contained my Java classes which I needed to provide my new STS extension.Next I modified my
pom.xml
file and changed the packaging from war
to jar
. My goal was to add this maven project later as a dependency to another project which would result as a lib in the STS war archive.Allocating dynamic network ports to avoid test failures caused by port collisions
To get a dynamic port binding for my test services, I added a nice maven helper to my build allocating free ports for me:<project> . . . <build> . . . <plugins> . . . <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>1.5</version> <executions> <execution> <id>reserve-network-port</id> <goals> <goal>reserve-network-port</goal> </goals> <phase>process-test-resources</phase> <configuration> <portNames> <portName>jettyServerPort</portName> <portName>jettyServerStopPort</portName> </portNames> </configuration> </execution> </executions> </plugin> <plugins> <build> <project>
To ensure that my test classes can know the correct location of my Mock Services I simply set these dynamic values as a system property, which can be picked up in my test class:
<project> . . . <build> . . . <plugins> . . . <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.8.1</version> <executions> <execution> <id>integration-test</id> <goals> <goal>integration-test</goal> </goals> <configuration> <systemPropertyVariables> <service.url>http://localhost:${jettyServerPort}/myRestService</service.url> <sts.url>http://localhost:${jettyServerPort}/SecurityTokenService/UT</sts.url> </systemPropertyVariables> </configuration> </execution> <execution> <id>verify</id> <goals> <goal>verify</goal> </goals> </execution> </executions> </plugin> <plugins> <build> <project>
Jetty Plugin Configuration
And here comes the really interesting part of telling Jetty to run with classes and configuration files from thesrc/test
project folder:<project> . . . <build> . . . <plugins> . . . <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>8.1.5.v20120716</version> <configuration> <systemProperties> <systemProperty> <name>java.security.auth.login.config</name> <value>login.jaas</value> </systemProperty> <systemProperty> <name>service.url</name> <value>http://localhost:8080/myRestService</value> </systemProperty> </systemProperties> <scanIntervalSeconds>5</scanIntervalSeconds> <webAppConfig> <resourceBases> <resourceBase>${project.basedir}/src/test/webapp</resourceBase> </resourceBases> </webAppConfig> <useTestScope>true</useTestScope> <stopKey>STOP</stopKey> <stopPort>${jettyServerStopPort}</stopPort> </configuration> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>start</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> <daemon>true</daemon> <connectors> <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"> <port>${jettyServerPort}</port> <maxIdleTime>60000</maxIdleTime> </connector> </connectors> <systemProperties> <systemProperty> <name>java.security.auth.login.config</name> <value>login.jaas</value> </systemProperty> <systemProperty> <name>service.url</name> <value>http://localhost:${jettyServerPort}/myRestService</value> </systemProperty> </systemProperties> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> <plugins> <build> <project>
I tried testing first with version
9.2.3.v20140905
of the Jetty plugin, but for some reasons I could not discover so quickly the SelectChannelConnector
would not work as expected. My test would always run at port 8080
instead of a dynamically picked port. Therefore I switched back to version 8.1.5.v20120716
and all was running as desired.The most important parts to mention here is to set the
resourceBase
in the configuration
to ${project.basedir}/src/test/webapp
as well as setting useTestScope
to true
.Since I still wanted to use the port
8080
when running mvn jetty:run
but a dynamic port when running mvn verify
, I had to override the port settings accordingly.After these changes I was able to build my extensions including the automated integration test, but without any test related code in my
src/main/
folder.
Hello,
ReplyDeleteThe informative Article on Integration Testing for STS Extensions with Jetty is good. It gives detailed information about it .Thanks for Sharing the information about Integration testing. Software Testing Services