When I do "mvn verify", I cannot get the spring-boot project to load the application properties - spring-boot

My project is on an isolated computer, so I can't do massive dumps of files, but I will try to provide the necessary information.
I have a Spring-Boot MVC project. I can get it to run fine from the command line. I can get the ApplicationContext to fun fine as long as I am using the Spring-Boot-Test starter:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
#TestPropertySource(locations = { "classpath:application-test-h2.properties" })
#DirtiesContext(classMode = ClassMod.AFTER_EACH_TEST_METHOD)
I have recently added some HTMLUnit tests to go do some integration testing. The tests run fine when I have the application already running (which means it can't be done automatically on the corporate Bamboo). So, after stumbling around the web, I added the cargo plugin:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.16</version>
<configuration>
<wait>false</wait>
<container>
<containerId>tomcat8x</containerId>
<type>embedded</type>
<logLevel>info</logLevel>
<container>
<configuration>
<properties>
<cargo.servlet.port>8443</cargo.servlet.port>
<cargo.protocol>https</cargo.protocol>
<cargo.tomcat.connector.clientAuth>false</cargo.tomcat.connector.clientAuth>
<cargo key and password stuff censored>
<cargo.tomcat.httpSecure>true</cargo.tomcat.httpSecure>
</properties>
</configuration>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals><goal>start</goal></goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals><goal>stop</goal></goals>
</execution>
</executions>
</plugin>
I also went to the maven failsafe plugin and did:
<execution>
<id>integration-test</id>
<goals><goal>integration-test</goal></goals>
</execution>
<execution>
<id>verify</id>
<goals><goal>verify</goal></goals>
</execution>
Finally I edited the spring-boot-maven-plugin and added:
<execution>
<id>pre-integration-test</id>
<goals><goal>start</goal></goals>
</execution>
<execution>
<id>post-integration-test</id>
<goals><goal>stop</goal></goals>
</execution>
So, I can finally see my application context start up when I do a "mvn verify". All is well and good, right up until it tries to connect to the database. I have 2 application.properties files and a application-test-h2.properties.
They are:
|--- ProjectDirectory
\--- src/main/resources
\--- application.properties (1)
\--- src/test/resources
\--- application-test-h2.properties (2)
\--- application.properties (3)
It appears from the error message that it is only picking up the application.properties noted by (1). The cargo startup does not appear to be getting (2) or (3) or using the precedence Spring projects use.
The integration tests are simple:
#RunWith(Theories.class)
public void HTMLUnitIT {
#Datapoints
private static MyTestObject[] datapoints;
#Theory
public void testSearches(MyTestObject obj) throws Exception {
//..... stuff ... This stuff runs if I just run the class and have the application running
}
}
So the $64,000 question is, how do I get the properties to all resolve in the cargo plugin?
Thank you in advance.

Related

Quarkus: how can I ignore tests written for different test profile and test tags

I'm strugling with finding info of how to ignore some tests that were exclusively written for some "other" profile when runing default mvn clean install.
I need different tests for different use cases:
CRUD operations on entities with hibenate-orm create-drop option
other operations on entities with hibernate connected to mock database (hence integration tests, with hibenate-orm validate)
I've got my custom test profile
public class IntegrationProfile implements QuarkusTestProfile {
#Override
public String getConfigProfile() {
return "integration";
}
#Override
public Set<String> tags() {
return Collections.singleton("integration");
}
}
And use it like this:
#QuarkusTest
#TestProfile(IntegrationProfile.class)
public class ArticleIntegrationRepositoryTest { ... }
I run these tests in cmd line like:
mvn -Dquarkus.test.profile.tags=integration clean install
But when I run
mvn clean install
all tests, including "profiled" ones are executed and I don't want that.
Is there any way to annotate these "other" tests so they don't get run unles I specificaly execute them with mvn -Dquarkus.test.profile.tags=integration clean install
Any help appreciated
I figured it out:
First I addet junit 5 tag to to my integrations test classes
#Tag("integration")
then I updated my pom.xml files accordingly.
For maven-surfire-plugin I added executions to ignore my integration tags on tests
<executions>
<execution>
<id>default-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludedGroups>integration</excludedGroups>
</configuration>
</execution>
</executions>
and added new integration profile to include only these tests when needed
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<id>quarkus-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<groups>integration</groups>
</configuration>
</execution>
</executions>
...
</plugin>
</plugins>
</build>
</profile>
now mvn clean install ignores my "integration" tests and mvn -Dquarkus.test.profile.tags=integration -P integration clean install executes only integration tests

Using sonar.test.exclusions with Sonarqube 6.3

I'm currently evaluating Sonarqube 6.3 (a big upgrade from my current 5.5 instance) and I'm getting confused trying to work out the functionality of the sonar.test.exclusions setting.
There's this question: Sonar Maven Plugin: How do I exclude test source directories? which seems to indicate that it is used to exclude test files from analysis (which is what I'm after - I don't want my sonar ruleset run over my unit tests). The documentation https://docs.sonarqube.org/display/SONAR/Narrowing+the+Focus also indicates that it is used to 'exclude unit test files' (perhaps this can be expanded upon to make it clearer?)
Thing is, when I add sonar.test.exclusions with a value of **/src/test/** and then run my analysis, I'm still getting code smells and the like being found for:
Foo/src/test/java/foo/bar/BarTest.java
Foo/src/test/java/lah/LahTest.java
etc.
When I use sonar.exclusions instead, they don't show up. Why is sonar.test.exclusions not doing what I expect?
First of all: if you have a Maven project, you should use the scanner for Maven (mvn sonar:sonar). It will simplify your configuration, and will automatically register src/test/java folder as a test directory.
Now if you want to do the configuration manually, or understand what is going on under the hood, here is the explanation: SonarQube scanner work with 2 sets of files, main and test. Main source files are configured using the property sonar.sources. Test source files are configured using sonar.tests.
On top of that, you can filter some content using the sonar.[test.]exclusions properties.
In you case your problem is that Foo/src/test/java/foo/bar/BarTest.java seems to be considered as a main source file. That's why sonar.test.exclusions has no effect.
Using maven with verfication goal (mvn clean verify sonar:sonar install), I have used this configuration without problems:
...
<properties>
....
<sonar.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.exclusions>
<sonar.test.exclusions>
src/test/**/*
</sonar.test.exclusions>
....
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.coverage.exclusions>
**/generated/**/*,
**/model/**/*
</sonar.coverage.exclusions>
<jacoco.version>0.7.5.201505241946</jacoco.version>
....
</properties>
....
Coverage exclusion configuration, inside properties (up) and jacoco plugin configuracion:
.....
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>target/jacoco.exec</dataFile>
<outputDirectory>target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
....

application-test.properties isn't loaded when activating profiles with <profiles>

I'm trying to use new feature from Spring Boot 1.3.0.RELEASE -- activate profile via configuration of spring-boot-maven-plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>test</profile>
</profiles>
</configuration>
<executions>
<execution>
<id>start-application</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-application</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
But in this case my integration test starts to fail, because of IllegalArgumentException: Could not resolve placeholder 'spring.mail.host' in string value "${spring.mail.host}"
This variable defined in src/main/resources/application-test.properties:
spring.profiles: test
spring.mail.host: 127.0.0.1
My test look like this:
#ContextConfiguration(
loader = AnnotationConfigContextLoader.class,
initializers = ConfigFileApplicationContextInitializer.class,
classes = TestContext.class
)
public class WhenAnonymousUserRegisterAccount extends AbstractTestNGSpringContextTests {
#Value("${spring.mail.host}")
private String mailHost;
TestContext only defines PropertySourcesPlaceholderConfigurer with another property files.
The interesting part is that if I remove <profiles> and activate profile from application.properties my test works:
spring.profiles.active: test
So, it looks like that when I'm using <profiles> Spring doesn't load application-test.properties file to the environment.
Questions:
is it a bug?
(if it's not) how to configure Spring to load application-test.properties and use <profiles>?
why these approaches are differ?
If you specify the profiles in the configuration of the spring-boot-maven-plugin then they are only available if you execute the application with that plugin, i.e. by running mvn spring-boot:run. I suspect, that's not the case for your integration test and thus it doesn't work.

maven surefire exclude by directory?

I'm using maven surefire and need to exclude my integration tests. My project layout is non-standard, I have src/main/com, src/test/com and src/integration/com.
By default when I run the test goal the integration tests and unit tests are run. I would like to exclude the integration tests... I've tired:
<excludes><exclude>**/integration/*</exclude></excludes>
But this results in no tests running. I then added an includes for the test, but still no tests run:
<includes><include>**/test/*</include></includes>
The first integration that is executed is under src/integration/com...
Also, if it matters this project is a subproject, so maybe that effects the path to exclude?
Any pointers on why I can't exclude these integration tests?
Include / Exclude path is relative on the default configuration of test 'src/test/java'.
And you can't have two sources for testing but you should use this alternative :
<testSourceDirectory>src/test/com</testSourceDirectory>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>TO DO</version>
<executions>
<execution>
<id>add-integration-test-sources</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/integration/com</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

Getting wrong coverage data with jacoco and maven

I have a project using jacoco version 0.7.1.201405082137 and maven 3.0.5. In the project I have some unit tests, and some tests created using arquillian.
To distinguish between the unit tests and integration ones, I created two junit categories: one called FastTest and another called SlowTest.
In the maven profile that I use to run all tests I have this plugins configured:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<groups>SlowTest,FastTest</groups>
<systemPropertyVariables>
<arquillian.launch>wildfly_8_x</arquillian.launch>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${version.jacoco}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
When I leave both categories in I get only the coverage for the tests annotated with SlowTest. But all the tests run. If I run only the ones annotated with FastTest I get their correct coverage too.
How can I set up jacoco to get the correct coverage when running both kinds of tests?
Small tip:
<groups> tag takes full class name. So my question: is SlowTest.class interface placed in the default package? If not you should provide full path, something like: <groups>com.mycompany.project.SlowTest</groups>
And little advice:
Good practice is to distinguish unit and integration tests - and thus run them separately. Maven accomplishes this by two plugins: maven-surefire-plugin and maven-failsafe-plugin.
First is designed to run unit tests with mvn test. Second is designed to run your integration tests with mvn failsafe:integration-test. This answer may be useful to shed some light.

Resources