hsql for unit tests maven - maven

I am using sql-maven-plugin to setup a in memory hsql database for unit tests
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.5</version>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.2.8</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>create-db</id>
<phase>process-test-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<driver>org.hsqldb.jdbcDriver</driver>
<url>jdbc:hsqldb:mem:test;shutdown=false</url>
<username>SA</username>
<password></password>
<autocommit>true</autocommit>
<srcFiles>
<srcFile>src/test/sql/test_db/test.sql</srcFile>
</srcFiles>
</configuration>
</execution>
</executions>
</plugin>
in unit tests that run in maven:test phase, I instantiated a datasource with that url
org.hsqldb.jdbc.JDBCDataSource ds = new JDBCDataSource();
ds.setUrl(URL);
ds.setUser("sa");
ds.setPassword("");
but this does not have the tables that i had initialized via the scripts. it turns out surefire forks a new jvm and the original hsql instance started is not accessible from there. Is there a solution without introducing a file backed hsqldb ?
Thanks

You could try turning off forking in surefire.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<forkCount>0</forkCount>
</configuration>
</plugin>
Or, you could instantiate the HSQL server directly in your unit test environment, so that HSQL is spawned within the forked Surefire JVM:
#BeforeClass
public static void oneTime() throws Exception {
org.hsqldb.Server.main(new String[]{});
}
#AfterClass
public static void oneTime() throws Exception {
BasicDataSource dataSource = ... // get your data source
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute("SHUTDOWN");
}
If you don't shutdown HSQL after your test class, you'll run into "Port already in use" type errors from trying to spawn a new db server for each test class.
Or, you could use a framework like Hibernate or DbUnit.

Have you considered using dbunit? That will also make it a lot easier to run the unit-tests from your IDE without requiring Maven or executing all its pre test phases.
Also, for a unittest is it required to use a database? You shouldn't be testing if a db connection could be made. Instead I'd prefer to mock such objects with something like mockito. It is about specifying what result you want for a certain sql statement.

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

Running Spock tests in parallel

My E2E tests are running pretty slowly (25 minutes) as they call a bunch of services and wait for some data to be populated in the database. I want to run it concurrently. I'm using the following maven-failsafe-plugin setup:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${plugin.failsave.version}</version>
<executions>
<execution>
<id>run-integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
And my test looks something like this (more information can be provided if it is needed):
#Stepwise
#DataJpaTest
#ContextConfiguration(classes = SomeControllerITConfig)
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class SomeControllerIT extends Specification {
// some variables definition
def "test1":
// some test
def "test2":
// some test
// some more tests
}
I tried to use threadCount property along with parallel or forkCount but nothing works for me. Also I tried to force the following dependency in the maven-failsafe-plugin dependencies:
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.16</version>
</dependency>
Thanks in advance!
I ended up with the following issue on GitHub:
https://github.com/spockframework/spock/issues/691
Comment or whatever if you're also interested in parallel test execution in Spock.
In short, I've found a pull request with enabling parallel execution and it is even merged into one of the branches. However it is not merged into master yet. So the only way out I see for now is to write my own custom BaseSpecRunner
Looks like Spock team added support for parallel execution:
http://spockframework.org/spock/docs/2.0-M4/parallel_execution.html#parallel-execution
requires groovy: >3.0.6

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);
}

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.

Intercepting MongoDB calls using AspectJ in a Spring project

I am using Spring and the MongoDB java driver and I am trying to intercept all calls on the mongo DBCursor object to view queries before they get executed.
I've been trying to do this using the aspject-maven-plugin for external jars.
http://mojo.codehaus.org/aspectj-maven-plugin/weaveJars.html
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<verbose>true</verbose>
<privateScope>true</privateScope>
<complianceLevel>1.5</complianceLevel>
<weaveDependencies>
<weaveDependency>
<groupId>org.mongodb</groupId>
<artifactId>>mongo-java-driver</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
I am already using Spring AOP and have aspecj configured in java code
#EnableAspectJAutoProxy
I am then adding the following to a class which uses the #Aspect annotation. (Other intercepts are working fine on custom classes which are in the source code of my project)
#Pointcut("execution(* com.mongodb.DBCursor..*.*(..))")
public void interceptAndLog(ProceedingJoinPoint invocation){
_loggingService.Info("intercepted DBCursor");
}
I have also tried replacing #Pointcut with #Before but neither work.
Thanks in advance,
Ronan

Resources