I have a Junit test case for testing a method which require some initial data. The data required is not part of the current schema used by my hibernate project. So I cannot use model object to create that insert data. Is there any way to run sql scripts before and after running junit test ?
The Non Hibernate way is the following
Process p = Runtime.getRuntime().exec("psql -U user -d db -h host -f file.sql");
How to handle this using hibernate ?
I solved this by running native sql query using the hibernate api
Query persistableQuery = entityManager.createNativeQuery("QUERY");
persistableQuery.executeUpdate();
The #Sql annotation is my first option.
Haven't tried it, but since you are using Spring, you can also use ScriptUtils in your #Before method:
Connection connection = dataSource.getConnection();
ScriptUtils.executeSqlScript(connection, new ClassPathResource("test_db.sql"));
There's also nice library called dbunit that allows to set database to known state before and after junit tests.
Related
I'm making an application for a school project, but I'm running into the issue that when I try to run the unit tests that it tries to connect to the database while starting up the application, which isn't required for the tests (because it will be mocked), and is not available in the CI/CD pipeline.
jdbc connection error
I'm building my project in Java Maven Springboot and would like to know how I can prevent it from trying to connect to the database when running my test.
here is a link to my repository: https://gitlab.com/kwetter_jack/Kwetter_posts/-/tree/ci_cd_setup
Your test classes have #SpringBootTest annotation which will start a Spring application context - as your application uses a database the tests will also try to setup and use a database connection.
The simplest solution is to remove the annotation so the tests no longer try to connect to a database. You'll probably need to mock some more dependencies as a result as Spring is no longer creating these for you. You could also have a look at https://www.baeldung.com/spring-boot-testing for some other ideas how you could alter your tests.
Alternatively if you do want / need the application context to run you can add a application.yaml for the tests that defines and uses a in memory DB so the tests have something to connect to - see https://www.baeldung.com/spring-boot-h2-database for details how to do this.
Just change value under spring.datasource to H2 database to prevent
The application connect the real database.
Test application.yml
FYI, You no need to copy all config from original application.yml, just only some config that you need to override.
while I was investigating the spring boot H2 in-memory database (as suggested by Chris Olive and Paranaaan) I also came across the option of using a test container. after looking into this I saw that this enables the project to create a temp docker container with a MySQL image that I can use during the testing of my project, considering I was planning on using docker anyway for the integration testing of my microservices project I attempted this and it worked as I had hoped it would.
if anyone is interested in the test container solution that I used, the information can be found here:
https://www.testcontainers.org/modules/databases/mysql/
I am using HSQLDB for JUnit Tests, the test data is provided by XML Files with dbUnit. Our application uses an Oracle DB in production.
In order to suppert Oracle-specific queries I have added the property sql.syntax_ora=true to the url like this:
db.url=jdbc:hsqldb:mem:unitdb;sql.syntax_ora=true
When I run my JUnit test I get the exception
org.hsqldb.HsqlException: The table data is read only
I have also tried to execute the query SET DATABASE SQL SYNTAX ORA TRUE;
but this gives me the same exception.
Please help me with this problem. Thanks!
I have this Spring Boot Application, where I have used h2 database to cover Junit test case. Everything is working fine until I have this new scenario where I need to execute a MySql query using jdbcTemplate.
The jdbcTemplate is to execute below query
'INSERT IGNORE INTO someTableName ......'
It is working fine when running the service and from postman getting successful response but jUnit test cases are started failing after this change.
I have used #DataJdbcTest annotation to support h2 database based jUnit test case.
I am pretty much sure the issue is due to IGNORE keyword in sql query, but I need to know if there is simple solution for this issue.
You could try h2's MySQL Compatibility Mode.
From their docs:
INSERT IGNORE is partially supported and may be used to skip rows with duplicate keys if ON DUPLICATE KEY UPDATE is not specified.
I am trying to run the integration test in spring boot which creates liqubase bean and run all the changesets. I get an error while running below change set in yaml file.
spring boot integration test run exception
- changeSet:
id: 2
author: XXX
changes:
- sql:
splitStatements: true
sql: CREATE ROLE dba_user LOGIN PASSWORD 'dba_user';
stripComments: true
Exception is
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE ROLE DBA_USER LOGIN[*] PASSWORD 'dba_user' "; SQL statement:
CREATE ROLE dba_user LOGIN PASSWORD 'dba_user' [42000-196]
Why does it add [*] or is there some other issue? The same exception I get while running changeset to create a view.
Your test is running against H2 database, which doesn't have CREATE ROLE feature.
BTW, I don't think it is good idea to create role via Liquibase. Liquibase is meant to be used for DB schema/data migrations, not for creating DB instance (where DB role creation falls as well). I would suggest to create role when DB instance is being created (doesn't matter if it is automated or manual).
If you have SQL queries that not compatible with H2, you can use testcontainers to use PostgreSQL with your integration tests. It runs docker containers under the hood for your database needs in tests and you can query the containerized PostgreSQL.
preConditions:
- onFail: MARK_RAN
- not:
- dbms:
type: h2
I found a way to skip database specific script with this. So it won't run if it's h2.
I have some problems with using a schema.sql file to create my sql schema when executing a junit test while this schema contains mysql specific expression. I have to add the mode=mysql to the H2 url.
For example something like this:
jdbc:h2:mem:testd;MODE=MYSQL
But Spring boot automatically uses the url defined in the enum
org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection with its url
jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE.
I have tried similiar approaches to get this to work, but spring does not take the spring.datasource.url=jdbc:h2:mem:testdb;MODE=MYSQL from my test-application.properties. All other settings from my test-application.properties have been read successfully.
If I let spring/hibernate create the schema (without the schema.sql file) with the javax.persistence annotations in my entities everything works fine.
Is there a simple way to add a mode?
Set
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
in application-test.properties, plus
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ActiveProfiles("test")
on the test class
I was having this same issue. It would not pick up the url when running tests. I'm using flyway to manage my scripts. I was able to get all of these working together by following these few steps.
Created a V1_init.sql script in src/test/resources/db/migration so that it is the first script run by flyway.
SET MODE MYSQL; /* another h2 way to set mode */
CREATE SCHEMA IF NOT EXISTS "public"; /* required due to issue with flyway --> https://stackoverflow.com/a/19115417/1224584*/
Updated application-test.yaml to include the schema name public:
flyway:
schemas: public
Ensure the test specified the profile: #ActiveProfiles("test")
I have tried similiar approaches to get this to work, but spring does not take the spring.datasource.url=jdbc:h2:mem:testdb;MODE=MYSQL from my test-application.properties
Did you try to append this parameters instead of rewriting the existing ones?
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
All other settings from my test-application.properties have been read successfully.
I thought that file should be named application-test.properties.
I was able to run it with this config:
# for integration tests use H2 in MySQL mode
spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_LOWER=TRUE;MODE=MySQL;
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
The main trick here is to force Hibernate to generate SQL scripts for MariaDB dialect because otherwise Hibernate tries to use H2 dialect while H2 is already waiting for MySQL like commands.
Also I tried to use more fresh MariaDB103Dialect for MariaDB 10.3 but it doesn't worked properly.
You need to set MYSQL mode on h2 and disable replacing of datasource url for embedded database:
Modify application-test.yaml
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=MYSQL
test:
database:
replace: NONE