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

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.

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

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

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.

Spring Boot profiles not active when set with maven plugin

I'm trying to set spring profiles when starting Tomcat for integration tests in maven like this:
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<profiles>
<profile>testProfile</profile>
</profiles>
</configuration>
...
The profile is definitely not active.
On the other hand the following does work and the requested profile is active:
<jvmArguments>-Dspring.profiles.active=testProfile</jvmArguments>
The problem here is that we can't stop the server, which is a problem when running automated integration tests.
I'm using spring boot "1.4.0.RELEASE".
My questions:
1. Why does the profile tag not work? (Bug?)
2. Why id the JMX bean not found when trying to shutdown the server in the "stop" goal? Does this something have to do with the forking because of the jvmArguments?
I was ignoring the args in the main method. Passing them to the Spring application solved it:
public static void main(String[] args) throws Exception {
SpringApplication.run(RunServer.class, args);
}

Binding a custom Maven plugin to a default phase

I have a custom Maven plugin that I'm trying to bind to the package phase by default. I've tried every combination of using the #Mojo annotation along with the #Execute annotation, but it doesn't seem to auto bind.
The only way I manage to get my plugin to work is by defining it like this:
#Mojo(name = "put")
public class SSHMojo extends AbstractMojo {
And then in my project using the plugin, defining an execution. I'd like to avoid having to add the <executions> every time I want to use my plugin.
<plugin>
<groupId>com.patrickgrimard</groupId>
<artifactId>ssh-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>put</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>devopsmtl</serverId>
<host>example.com</host>
<remoteDirectory>/srv/www</remoteDirectory>
</configuration>
</plugin>
My full plugin pom can be found at https://github.com/pgrimard/ssh-maven-plugin/blob/master/pom.xml
Hi simply use the following:
#Mojo( name = "put", defaultPhase = LifecyclePhase.PACKAGE )
Apart from that i would suggest to use a newer version of maven-plugin-api (3.0 at least)...
Use annotation attribute defaultPhase (like already mentioned by khmarbaise):
#Mojo(name = "put", defaultPhase = LifecyclePhase.PACKAGE)
public class SSHMojo extends AbstractMojo { ... }
In the pom.xml of the consuming Maven project you can leave away the reference to the phase after this:
<plugin>
<groupId>com.patrickgrimard</groupId>
<artifactId>ssh-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<!-- <phase>package</phase> --><!-- needed no longer -->
<goals>
<goal>put</goal>
</goals>
</execution>
</executions>
...

Using DB unit to load DEMO data

I'm using the Maven DBUnit plugin to load test data for unit tests. I'd also like to use it for loading a different set of data to a different db for demo purposes. The dbunit plugin only allows for a single execution. Should I just create a separate pom or is there some trick that I can do to make this happen. (I.e., I'd like to simply do something like mvn load-demo-data).
you can execute a plugin several times if you like it depends just on the configuration you give in the pom:
<plugin>
<artifactId>maven-whatever-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
....
</configuration>
<goals>
<goal>WhatEverGoalYouHave</goal>
</goals>
<phase>...</phase>
</execution>
<execution>
<id>execution2</id>
<configuration>
....
</configuration>
<goals>
<goal>WhatEverGoalYouHave</goal>
</goals>
<phase>...</phase>
</execution>
</executions>
</plugin>
You can also define a profile to control the execution which might the right choice for your demo data. The call you described mvn load-demo-data is not possible with maven, cause maven calls only a goal or lifecycle.
Use properties when configuring the database credentials
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>dbunit-maven-plugin</artifactId>
<version>${dbunit.plugin.version}</version>
<configuration>
<url>${db.url}</url>
<driver>${db.driver}</driver>
<username>${db.username}</username>
<password>${db.password}</password>
</configuration>
..
Then add a profiles section to your POM, controling the setting of these properties:
<profiles>
<profile>
<id>db1</id>
<properties>
<db.url>jdbc:h2:target/db1;AUTO_SERVER=TRUE</db.url>
<db.driver>org.h2.Driver</db.driver>
<db.username>user</db.username>
<db.password>pass</db.password>
</properties>
<profile>
<profile>
<id>db2</id>
<properties>
<db.url>jdbc:h2:target/db2;AUTO_SERVER=TRUE</db.url>
<db.driver>org.h2.Driver</db.driver>
<db.username>user</db.username>
<db.password>pass</db.password>
</properties>
<profile>
..
The profile cane be activated as follows to update two different databases
mvn -Pdb1 clean test
mvn -Pdb2 clean test

Resources