Executing Spring Boot Integration tests on existing mysql database - java

I am using spring boot 2 and I am trying to execute integration tests on repositories by creating tests with annotations:
#RunWith(SpringRunner.class)
#DataJpaTest
public class SomeTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private SomeRepository repository;
// CONTENT
}
I have liquibase migrations and I want those tests to be run on special mysql database. However spring boot by default is trying to configure embeded h2 database. And after removing h2 dependencies from POM file I have got:
Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of #AutoconfigureTestDatabase
When I run my application it runs perfectly fine, since I have filled application.yml with proper database connections. However when I add application.yml to test resources nothing happens.
Can anyone tell me how to configure those tests properly to use mysql database?

Related

Unit testing a Configuration in spring Batch which runs in spring boot application

I am Using Spring boot application to run spring batch and I have a Config java class which loads all configuration related stuff like getting some values from properties file and setting them, calling reader,writers etc.
I am trying to run a junit for just few methods in that config class from my unit test class. how can we achieve that. I am trying to use SpringRunner Can someone through some light .

How to add the mode=mysql to embedded H2 DB in Spring Boot 1.4.1 for #DataJpaTest?

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

Configuring in-memory or embedded database to test production code

I have a requirement where in I have to test a DAO java class in production code using an in-memory database. The DAO performs insert operation using a different connection configuration.
I tried configuring hsql embedded database which comes with spring but looks like it needs programmatic configuration setup within the DAO production code for it to work but I cannot change the production code. Can someone suggest me a way to configure a embedded database to test my production DAO code through junits.
I tried this configuration:
#Before
public void setUp()
{
db = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript("create-table.sql").addScript("insert-data.sql").build();
}
But this above code is in my junit. Without this above code I am not seeing a way to configure the in-memory database. I cannot have this code in my production environment. How can I configure the in-memory database without making changes to the production code.
I created a TestConfig as my spring configuration file for my junits, and configured two beans in there:
EmbeddedDatabase bean to return the embedded database.
#Bean
#Profile("test-profile")
public EmbeddedDatabase embeddedDatabase()
{
return new EmbeddedDatabaseBuilder().setName("Derby").setType(EmbeddedDatabaseType.DERBY).addScript("schema.sql").build();
}
Then a bean for getting the Connection out of the above created database.
#Bean
#Profile("test-profile")
public Connection connection() throws SQLException
{
return embeddedDatabase().getConnection();
}
My production code gets the Connection object from spring's ApplicationContext. So I configured my junits to run using my TestConfig so the production code pulled in the embedded database connection object and passed it along. The tests passed.

Spring Boot with datasource when testing

I am using Spring Boot application and the auto cofiguration is enabled. The main Application file is marked as #EnableAutoConfiguration. The datasource is lookedup from JNDI is configured using java config and the class which create the datasource is marked as #Configuration.
I have a test class as below.
#RunWith( SpringJUnit4ClassRunner.class )
#WebAppConfiguration
#ContextConfiguration( classes = Application.class )
public class TestSomeBusiness {}
The issue is when I run the test case, the datasource jndi lookup happens, which fails because the test case is not running inside a server environment. As far as I know the classes in classpath marked with #Configuration are executed and that the reason the datasource lookup is being called.
The work around for now I have found is instead of JNDI lookup create the datasource using DriverManagerDataSource, so that even if its not a server environment the datasource lookup won't fail.
My questions are:
1) How do we generally deal with datasource (when looking up from JNDI) in
spring boot application for testing ?
2) Is there a way to exclude the datasource configuration class from being called when executing test case ?
3) Should I create an embedded server so that the JNDI lookup can be done when executing test case ?
2) Is there a way to exclude the datasource configuration class from being called when executing test case ?
You can add a application.properties config file into your src/test/resources and spring boot would pick those configurations in test environments. I suppose, you have application.properties in your src/main/resources like this:
spring.datasource.jndi-name=some_jndi
This JNDI resource will be used in your production environment. For your test environment you can use a, say MySQL database, by adding these configurations into your test application.properties:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
3) Should I create an embedded server so that the JNDI lookup can be
done when executing test case ?
As i said, you can totally bypass the fact that you're using JNDI for production by adding test specific configurations.
1) How do we generally deal with datasource (when looking up from
JNDI) in spring boot application for testing ?
You can mock JNDI resources using facilities available in org.springframework.mock.jndi package. For example by using SimpleNamingContextBuilder you can:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("jndi_name", dataSource);
builder.activate();
The other option is, of course, using Non JNDI resources in test environments.

Spring4 JUnit tests : Load SQL to a H2 db

I'm trying to write tests for a Spring Boot (Spring 4) Application.
My Junit test class is configured like this to allow autowired.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringApp.class)
public class MyServiceTest {
...
My src/main/resources/application.properties is like this
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost/mydb
spring.datasource.username=BNF0016779
spring.datasource.password=
In test context, src/test/resources/application.properties is just empty.
In can query the db as usual, creating objects...
But I'd like to create a data init sql.
To begin with a strange behavior, It seems that Spring loads any "schema.sql" in classpath.
Something like the following is not required ?
//This is not required to execute schema.sql
#Configuration
public class DatabaseTestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.build();
}
}
Then, I can't create any Table from this SQL.
Always receive org.h2.jdbc.JdbcSQLException: Table "MY_TABLE" already exists; SQL statement:
H2 is supposed to be a in-memory DB, no keeping data between two startup !
Why do I receive these errors ?
Any ideas ?
Thanks
Spring Boot will in fact execute a file named schema.sql in the root of the classpath by default. Furthermore, Spring Boot will also automatically create an embedded database for your application unless you instruct it otherwise. Consult the "Initialize a database using Spring JDBC" section of the Spring Boot reference manual for details.
H2 is supposed to be a in-memory DB, no keeping data between two
startup !
Yes and no.
If Spring Boot creates an embedded H2 database for you, yes it will be in-memory.
However, the database is actually a bean in the ApplicationContext (just like any other Spring-managed component). Thus it lives as long as the ApplicationContext lives, and the Spring TestContext Framework caches contexts between tests: that's one of its main features. In other words, the embedded database will not be recreated between tests (unless you annotate your test classes or test methods with #DirtiesContext). Consult the Context caching section of the Spring Framework reference manual for details.
Regards,
Sam (author of the Spring TestContext Framework)
H2 can be in memory. But I'm assuming the default DataSource it uses is not.
You can set the DataSourceFactory on the EmbeddedDatabaseBuilder to generate a DataSource that connects with a url such as jdbc:h2:mem:test.

Categories

Resources