How can use an in-memory H2 database when testing my Quarkus application? - quarkus

I plan to use PostgreSQL as the database for my Quarkus application but I would like the convenience of using H2 in my tests.
Is there a way I can accomplish such a feat?

Quarkus provides the H2DatabaseTestResource which starts an in memory H2 database as part of the test process.
You will need to add io.quarkus:quarkus-test-h2 as a test scoped dependency and annotate your test with #QuarkusTestResource(H2DatabaseTestResource.class).
You will also need to have something like:
quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:test
quarkus.datasource.driver=org.h2.Driver
in src/test/resources/application.properties
In order for the application use PostgreSQL as part of its regular run, quarkus-jdbc-postgresql should be a dependency and
quarkus.datasource.url=jdbc:postgresql://mypostgres:5432
quarkus.datasource.driver=org.postgresql.Driver
should be set in src/main/resources/application.properties
Update
As of version 1.13, Quarkus can launch H2 automatically in dev and test mode when quarkus-jdbc-h2 is on the classpath and no URL configuration is provided.
See this for more information.

You can use the below configurations in the application.properties file to use h2 database
quarkus.datasource.jdbc.url=jdbc:h2:mem:default
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=admin
quarkus.hibernate-orm.database.generation=drop-and-create

Related

How to make a Spring Boot project dependency use H2 database

I have a Spring Boot project (MAIN) which in turn depends on a (DAL) dependency.
DAL is where every Entity, Repository, Projection and Spring Data JPA related configurations are.
Now, MAIN project is a scheduler, and I need to make some integration tests over it. As always I want to use H2 database for the job in hands.
I have the H2 configuration under /test/resources/application.properties and this configuration have always worked if the JPA related classes were in the same project.
But in this specific case what is happening is that the H2 configuration are being ignored and the Integration Tests are writing into the real database.
Is possible to make the DAL to use H2 configurations?
For future reference, seting up H2 configuration for nested projects is very much possible.
The reason I was unable te setup this configuration rigth on the first attempt was because on DAL I have configured multiple data sources, as such the default h2 configuration wouldnt be enought.
So I had to make something like the folloing:
first-datasource.driver-class-name=org.h2.Driver
first-datasource.jdbcUrl=jdbc:h2:mem:testdb
first-datasource.username=sa
first-datasource.password=password
second-datasource.driver-class-name=org.h2.Driver
second-datasource.jdbcUrl=jdbc:h2:mem:testdb
second-datasource.username=sa
second-datasource.password=password

How to disable Javers for integration tests?

I am using Javers 3.11.2 with Spring Boot 1.5.17. When I am trying to run integration tests on an embedded database I still see that Javers tables are getting created each time.
Is there a way I can disable Javers during these tests so that these tables will not be created each time?
There is the easy way, put:
javers:
sqlSchemaManagementEnabled: false
in your application-test.yml. See https://javers.org/documentation/spring-boot-integration/
Disclaimer: I've never used Javers.
In general, disabling something in "integration tests" means that you don't want to load some beans (of Javers in this case).
This means in turn that you have to exclude them from the list of configurations spring boot works with.
If you're using javers autoconfiguration module, it has to provide in its own "spring.factories" file (can be found inside the jar) a file for autoconfiguration.
Find its java code and see whether it has some "#Conditional on something (property beans, etc.)" If it has than create a profile for integration test that will configure the beans in a way that conditional in javers won't pass and the bean won't be created as a consequence
If it doesn't have a conditional on something like this, you'll have to exclude the whole configuration. Its usually can be done by annotation #SpringBootApplication(exclude=<JaversAutoconfiguration goes here>
This will, however, turn it off also for production usage, which is obviously not something that you want. So for "production" profile, you'll have to import it as a regular configuration (not an autoconfiguration), for integration test profile you won't need this.

How to configure Spring Boot Application to run on a specific database when launching

I have a Spring MVC Application developed with Spring Boot. This is application is just for learning purposes, by the way.
By default, the app launches and uses a MySQL database. For unit and integration testing, I use an in-memory H2 database and it works perfectly.
So for that, I have two application.properties. One is under /src/main/resources/application.properties.
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost/myDatabase
spring.datasource.username = root
spring.datasource.password = mysql
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.cache=false
The other application.properties in under /src/test/resources/application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
spring.datasource.username=sa
spring.datasource.password=sa
Now, I have to use Selenium for automated website testing and I don't want my MySQL database to be populated with test data.
I haven't done this previously in Spring, but I would like my application to work like this:
Launch from terminal my application with certain commands specifying what database it should use. It should launch on localhost:8080
And then, run all Selenium test in localhost:8080. All the data generated with Selenium tests is only kept in memory as long as the application is running
How to do this in a Spring Boot Application using an application.properties or other configuration?
Create a separate properties file named application-test.properties and place it under /src/test/resources. The test database properties (or any other test specific properties) should go here.
On top of your test class, use this annotation #ActiveProfiles("test").
#ActiveProfiles("test")
public class MyTest {
...
}
Spring should do this for you automatically. To run application.properties from src/test/resources when you are running tests because spring runs with "test" profile. If not, add #ActiveProfiles("test") annotation on your test class (and by that I mean the class where you have your tests, not the class under test). If even that doesn't work, you can rename your src/test/resources/application.properties to src/test/resources/application-test.properties and select your profile in your run configuration (there is a field called 'profile'). Reference and more info.

Spring Boot use separate user for flywaydb and JPA

flyway.password=pwd2 #does not take effect
flyway.user=user2 #does not take effect
spring.datasource.username=user1
spring.datasource.password=pwd1
user1/pwd1 is used to run flyway db migrations as well as DML operations via JPA. Is there a way to get flyway db to use another credentials?
I got it to work by specifying flyway.url too.
It seems you are mixing the Spring config file with the Flyway config file. Try putting the Flyway config in a flyway.conf file instead of Spring's application.yml config file.
Alternatively, you can use Flyway environment variables like SPRING_FLYWAY_USER and SPRING_FLYWAY_PASSWORD. This is usually a good practice (secured) on cloud environments, as it can be filled from so-called secrets.

How to configure different data sources for local testing and deployment in Spring Boot Application

I am trying to find the best way to configure my Spring Boot Web application to easily switching between the following data sources for both local testing and deployment.
H2 in memory db. Local testing only.
Dev oracle. Local testing and deployment.
Prod oracle. Deployment only.
By local testing, I mean to test in IDE environment (Eclipse). Dev and prod oracle databases are set up on two remote servers.
After some research, there are different ways to switch from one data source to another.
Use Spring profile. Using H2 and Oracle with Spring Boot. Set up the following files in classpath, application.properties, application-h2. properties and application-dev.properties. While connections for h2 and dev are defined in corresponding properties files, spring.profiles.active is set in application.properties. My understanding is this property can be overridden during build process by specifying spring.profiles.active. However, it seems to be a JVM variable, how do I set it running maven?
Maven profile. Create multiple profiles in pom and a filter pointing to application properties files. The profile specified by -P option during maven build will determine which application properties file to look. However, according to maven application with multi environment configuration can't deploy on tomcat, this will generate multiple wars for different deployment. So method 1 is preferred. Plus, it does not apply to switching datasources while testing locally.
Persistence units. Define different persistence units for different data sources in persistence.xml. Use EntityManager by choosing a specific unit. Variation of this method include having a variable in unit names which is determined in application.properties.
JNDI lookup. Set up a jndi name in application.properties with spring.datasource.jndi-name. The actual database information including url and credentials will be specified in context.xml in the tomcat folder where the war will be deployed.
My mind is set on local testing environment. Gonna go with method 1. Switching between H2 in memory and oracle is so easy just by changing the property in application.properties. Since the testing is usually done in IDE, war does not need to be generated, although answers are welcome for run maven install with spring.profiles.active.
As far as deployment, JNDI is definitely the way to go. However, I am concerned that the two properties in application.properties: spring.profiles.active and spring.datasource.jndi-name may be conflicting with each other. If I have spring.profiles.active=h2 and then tried to deploy the war to prod server, does it try to connect to h2 based on the spring profile or to prod db based on jdni-name? What is the best practice to accommodate all scenarios with enough flexibility?
Also is a explicit configuration class for DataSource required such as Configure Mutiple DataSource in Spring Boot with JNDI? My understanding is application.properties and spring profile should be enough to handle it, right?
Definitely use Spring profiles.
You don't want to use Maven profiles as it creates different artifacts. Ask your QA/Release engineers how they feel about having different artifacts for different environments :). They wouldn't be happy.
H2 is what you want to use in CI server integration testing as well. Such integration testing is fast and easy.
Instead of changing profile in application.properties, consider defining profile via command line parameter. So that configuration file changes are not required to run your application in different profiles.

Resources