I have complex web application using Spring,Hibernate, Maven joint build(Java+Groovy) with test in Spock and different Maven profiles. All source files are in Java. I have Maven configuration(part of it) for local testing:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<path>/services</path>
<port>8062</port>
<contextReloadable>true</contextReloadable>
<backgroundProcessorDelay>2</backgroundProcessorDelay>
<contextFile>../context.xml</contextFile>
</configuration>
</plugin>
So when I have changes in the bytecode maven contextReloadable triggers redeploy of the app. That is the desire state. When I run some test with maven configuration usingin InteliJ, in my system I see that redeploy is triggered.
I have no changes in the files or in the tests. But redeploy is triggered and everything is OK. But there is a problem for the same test when I click right button and click run on UploadTest using InteliJ 14.0.3 Community Edition
Redeploy happens but the profiles are not taken under consideration and the environment variables are not set. If I add them
org.apache.catalina.core.ContainerBase backgroundProcess WARNING: Exception processing loader WebappLoader[/services] background process java.util.ConcurrentModificationExceptio
And my backendSystem crashes. So my questions are:
Why InteliJ triggers redeploy when run Spock test without changes in the code/tests?
Why starting a single Spock test using InteliJ, cause my backednSystem brokes(I need to restart it)(what can be the source of the problems?? InteliJ runs the test with diferent parameters, profiles are not taken or ...).
Does inteliJ start compilation of the test with different eviroment variables set? (I see that inteliJ start its own launcher for the test).
Related
I am working on a simple spring boot application (created from spring initializr contains web mega-dependency).
I added also Cucumber dependencies for acceptance test.
When I run mvn clean install it runs directly the cucumber test, but me I want to run the app before tests (And why not stop the app after the tests terminate).
I tried maven exec plugin but it does not work:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions><execution>
<goals><goal>java</goal></goals>
</execution></executions>
<configuration>
<mainClass>org.dhappy.test.NeoTraverse</mainClass>
</configuration>
</plugin>
Skipping tests
If there is a need to skip tests and just compile and package the application, you can set the skipTests property as follows:
mvn install -DskipTests
Application execution
If you want to run the application, you can use the exec plugin. There are two flavours ("goals" really): one runs the package application and the other runs a Java class. If you know the class name, you can run that plugin as follows:
mvn exec:java -Dexec.mainClass="org.dhappy.test.NeoTraverse"
Integration testing
Finally, if you want to run the application first before you can run the tests, you are actually not doing unit testing. Your tests in this case are perhaps integration and not unit tests. The actual details would vary depending on whether your application has complex needs such as a database and a web server.
Integration testing happens at a different "phase" in maven lifecycle.
In short, you need to rename your Java test classes something other than *Test.java so that maven surefire plugin ignores your tests. You then need to include maven-failsafe-plugin so that integration testing happens.
You want to perform these steps:
Start the application
Run a set of tests
Stop the application
Starting and stopping the application is one thing and could be done in the <phase>pre-integration-test</phase> and <phase>post-integration-test</phase>. Integration testing is done in the <phase>integration-test</phase>
You want to read and understand https://maven.apache.org/surefire/maven-failsafe-plugin/usage.html. Specifically, look at the Using jetty and maven-failsafe-plugin example.
I have a multi-module Maven project with two modules being Spring Boot applications. Each of them has a simple test that the Spring application context loads successfully (my tests are very similar to this one). I run this tests with the following command in project root:
mvn -P IntegrationTests clean test
During context initialization things go out of my control, the application "eats" memory (heap size grows quickly to 4 gigabytes) and then the context fails to start with java.lang.OutOfMemoryError: PermGen space error (yes, I run it in Java 7).
Monitoring task manager during testing I noticed that maven spawns two new processes that have something to do with surefire plugin. I have no idea where it comes from, because I don't add the surefire plugin in my pom.xml.
Previously when encountered the same error somewhere I specified VM options (-Xmx256m -Xms128m -XX:MaxPermSize=256m -XX:PermSize=128m for example) and the problem was solved.
This time I tried to
set MAVEN_OPTS environment variable
set VM options (when running mvn test in IntelliJ IDEA) - it affected main java process but not its children
add -Drun.jvmArguments="..." in command line
but the problem persists.
Please help me to fight the OutOfMemoryError in tests.
Add Surefire plugin explicitly to module-specific pom.xml and configure VM options there. I like this solution because this way VM options are
passed to the spawned surefire processes (which should solve your problem)
affect only test application builds
shared between developers in your team
configurable independently for every module
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx256m -Xms128m -XX:MaxPermSize=256m -XX:PermSize=128m</argLine>
</configuration>
</plugin>
<!-- your other plugins go here -->
</plugins>
</build>
Problem statement
How to invoke tests within a given test server(i.e. within the process)?
Explanation
We know that there is surefire plugin, but this uses surefire:test goal which runs unit tests in separate process. In my case, i need to run the tests within the existing process (pre-configured test server and required environment) to run test. In surefire plugin, there is configuration that has forkCount and reuseForks. If i use it with forkCount as 0, reuseForks true, still creates separate server and hence process. I simply want to avoid setup part for test.
Update after Joe's comment saying it as duplicate As my application usage SpringBoot, running mvn clean install build the project and execute tests. While executing tests, it creates server for each running test. Even though i used configuration given below, in console it shows same process id, but starting server every time. In my case i don't want to make server up for every test case, rather used pre-existing test server and the test should use that server.
Configuration used
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<forkCount>0</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
We have a series of unit tests and they were passing fine prior to me trying to add some aspects for dependency injection and logging duration of methods being called in our rest end points.
In the unit tests prior to the tests failing, we get two odd errors:
[AppClassLoader#14dad5dc] error aspect 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' woven into 'com.lutherconsulting.aphirm.rest.ClientRest' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
and
[AppClassLoader#14dad5dc] error aspect 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' woven into 'com.lutherconsulting.aphirm.log.DurationLoggingAspect' must be defined to the weaver (placed on the aspectpath, or defined in an aop.xml file if using LTW).
We are using the aspectj maven plugin to just let it autoweave the aspects into the web application. The configuration for that from our pom.xml for Maven is below.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>test-compile</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
The strange thing is that this all works perfectly fine if I build the war file and deploy it to a Tomcat instance, or if I run all of our cucumber feature tests. When I do either of those, The aspect weaves fine and I get data on the duration of the rest methods I annotated logged to a database correctly. If I run a specific test package from intelliJ or try to run all junit tests in intellij, it fails with those two errors
Is this something I'm just missing in Intellij as a run/debug configuration in the way it executes unit tests? I didn't think our structure of our app was different than any normal web app
- src
| - main
| - java
| - packages
| - resources
| - test
| - java
| - packages
| - resources
- pom.xml
I appreciate any ideas on
In the end, what turned out to fix this was to go into the project structure in IntelliJ, on the AspectJ settings there is a check box for Post-Compile Weave Mode. Checking this made sure weaving occurred in Intellij prior to the tests executing.
As far as I understand you are running your tests from IntelliJ using its own runner and not maven.
Therefore you have configured the weaver to be run using maven through the aspectj-maven-plugin. The problem is that your IntelliJ runner is not running maven, hence its weaver plugin is not being run either.
I can come up with an idea and you could run your maven test goal within IntelliJ to run all your tests with the maven configuration, so it will detect aspectj-maven-plugin and run the weaver too. Here you can check how to run maven goals:
https://www.jetbrains.com/idea/help/executing-maven-goal.html
On the other hand, according to this link you have to enable Load Time Weaving in IntelliJ
http://www.aspectprogrammer.org/blogs/adrian/2006/02/a_practical_gui_2.html
Quoting the link it says:
Open the "Run/Debug Configurations" dialog using the drop-down in the
toolbar. Click the "+" icon to create a new configuration and name it
e.g. "tests".
For this project, I've selected "All in package" and search for tests
"In whole project".
Now all you have to do is add the VM startup parameter that brings in
the AspectJ LTW agent:
-javaagent:lib/aspectjweaver.jar
The part after the ":" should be the path to your copy of aspectjweaver.jar. In this case, I've copied the
aspectjweaver.jar from the Spring distribution into the lib directory
of my project (it doesnt' need to be on the project's classpath). You
can use the jar from AspectJ 5 final release too if you want to.
Also, you can check to configure AspectJ facet, check this link to read about it
https://www.jetbrains.com/idea/help/aspectj.html
I have followed this link to debug maven test via Intellij Idea : http://www.grygoriy.com/2012/01/how-to-debug-tests-maven-test-via.html
When reaching the third step and starting debugging, It's connected but quickly disconnected and isn't stopped in breakpoints. I had in Intellij :
Connected to the target VM, address: 'localhost:5005', transport: 'socket'
Disconnected from the target VM, address: 'localhost:5005', transport: 'socket'
Any idea ?
The only thing that prevents Idea from debugging Maven's goals is forking.
Plugins such surefire and spring-boot are using forking by default.
So, when you start debuging maven goal from IDEA it connects to maven, but process that you are really want to debug distincts from maven process, so it doesn't connected.
To prevent such behavior in surefire plugin you should read this article: http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html
In short:
If you use old surefire:
<configuration>
<forkMode>never</forkMode>
</configuration>
In new surefire:
<configuration>
<forkCount>0</forkCount>
</configuration>
But it's not much clear:
in case of CI (i wish you are using CI tools) you are not have prevent forking while it's much slow
if you ship your project to others - they will not be happy if some of modules behave in not default way
So if you want to please CI, IDEA, co-developers and yourself you should provide more smart way to allow debugging you build.
My suggestion:
default behavior is forked because build process is very often thing, while debugging it - is exception
debugger behavior is isolated with simple to use "switch on"
My variant:
<properties>
<test.forkCount>1</test.forkCount>
</properties>
<profiles>
<profile>
<id>debug</id>
<properties>
<test.forkCount>0</test.forkCount>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<!-- surefire -->
<configuration>
<forkCount>${test.forkCount}</forkCount>
</configuration>
</plugin>
</plugins>
</build>
So, in IDEA you just require to create named Run configuration with goal test and include debug to profile list.
But in other contexts - maven behaves still by default.
Where is addition profit - you can incapsulate whole debug behavior in single profile.
For example in my real project debug profile:
swith off forking on spring-boot:run
switch off JaCoCo coverage (it requires forking on surefire)
keep building Docker images locally but prevents pushing to registry
keep full packaging process but prevents publication to nexus
redirects SOAP UI functional tests to specital URL for local debugging
redirects DBCONFIG to docker-based Postgres that is "always empty"
downgrades loglevel for log4j to DEBUG
So if I use mvn <any> -P debug i'm sure that my environment and process is really debug
But if i ran mvn deploy on CI - i will get full stack of my building process.
This can also happen if e.g. the annotation BeforeAll is incorrectly used. IntelliJ swallows problem during the test initialization.
In my case the BeforeAll method was not static:
Incorrect:
#BeforeAll
private void beforeAll() {
}
It can also happen if the BeforeAll method is failing and the test is not started. Using mvn verify should print the error message in these cases.