Spring Boot: How to setup test data with liquibase in unit test - java

I'm trying to setup the database schema and some test data with liquibase for some tests. Each test has a separate changelog which setup the schema and some specific data for the test.
In order to make my tests working, I need to drop the schema before each test and fill it with new test data. However, it seems that this is not working because some tests are failing because the old test data is still available. I think something with my configuration is not correct. How can I force liquibase to drop the schema before each test?
My tests look as following:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyTestConfig.class)
#TestPropertySource(properties = "liquibase.change-log=classpath:changelog/schema-with-testdata.xml")
public class MyRepositoryTest {
The config for the tests looks as follows:
#SpringApplicationConfiguration
#Configuration
#EnableAutoConfiguration
#ComponentScan("com.mypackage")
#EntityScan(basePackages = { "com.mypackage.domain" })
#EnableJpaRepositories(basePackages = { "com.mypackage.domain", "com.mypackage.infra.persistence" })
public class MyTestConfig {
And the application.properties under src/main/test/resources is
liquibase.drop-first=true
spring.jpa.hibernate.ddl-auto=none

There is a spring.liquibase.dropFirst config property. Maybe this is what you're looking for?

Not sure if this completely answers your question. There is another property liquibase.default-schema=schemaNameToCreate
But even with that I was never able to get it to create the schema from scratch.

Related

Spring test XML configuration is overwritten by main XML configuration

Precondition
I have two XML configuration files one in src/main/resources which is called main-config.xml and used by the codebase, and one in src/test/resources which is called test-config.xml.
I wrote some integration tests and I wanted to load the test-config.xml into the context in the following way
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT,classes = { IntegrationTest.ITContext.class})
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class IntegrationTest {
#Configuration
#EnableAutoConfiguration
#PropertySource("classpath:application.properties")
#ImportResource("classpath:test-config.xml")
public static class ITContext{
....
}
}
The problem
In my main-config.xml there are some beans which I don't want to use in my test-config.xml. I have deleted these beans from test-config.xml, but for some reason they are still loaded into the integration tests context.
What I want to achieve?
I want to fully separate the main config file from the test config file.
Question
How can I achieve the wanted result with XML configuration? Which annotations am I missing?
Thanks in advance!

Configure H2 database for testng Spring

I need to make tests with embedded database and I want to check results in h2-console. I have configured properties for tests and I want to store my test data to have a look on it, but it always writes Replacing 'dataSource' DataSource bean with embedded version and uses another h2 DB like "jdbc:h2:mem:1f4af8a8-3e14-4755-bcbd-5a59aa31033e". What can I do with this problem?
"application-test.properties":
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./subdirectory/demodb
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
My test class:
#DataJpaTest
#ActiveProfiles("test")
class ProductRepositoryTest {
#Test
void findByProductName() {
//...
}
}
By default, the #DataJpaTest annotation replaces your production DB with an embedded one, wraps every test method in a transaction and rolls it back at the end of the test.
If you want to run your test as if it was a "real" operation on the DB, you can add the following annotations to your test class:
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#Transactional(propagation = Propagation.NOT_SUPPORTED)
The first one tells Spring not to use the embedded DB, while the second one tells it to work non-transactionally (every query will be persisted).

spring boot test loads schema.sql defined in java/resources instead of test/resources

I have the following Test:
#RunWith(SpringRunner.class)
#ContextConfiguration
#SpringBootTest(classes = {AccountsServerTest.class, PostgresSQLTestDbConfig.class})
#ActiveProfiles("test")
public class NodeRepositoryTest {
......
}
and also I have schema.sql and data.sql scripts under src/main/resources which are supposed to be run when the app starts.
I also have another two sql files under src/test/resources/ and I want to run them when NodeRepositoryTest is started.
However, for some reason, when I start NodeRepositoryTest, scripts from src/main/resources are executed.
Perhaps, someone had the same problem before?
I would really appreciate any help,
Thanks
You can manually define the .sql scripts which should be applied to your test method/test class.
Have a look at the following example from the official documentation (https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html):
#Test
#Sql({"/test-schema.sql", "/test-user-data.sql"})
public void userTest {
// execute code that relies on the test data
}

JUnit Test Cases for Config

I have a javaconfig file that looks like this:
#Configuration
public class ServiceConfig {
#Autowired
FooBean someBean;
#Bean
#Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public FooService fooService() {
return new FooServiceImpl(someBean, fooB());
}
private Foo fooB() {
return new FooB();
}
}
And I have created a junit test file like so based on this stack answer :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ServiceConfig.class)
public class ServiceConfigTest {
}
But I have a couple questions:
Should I test all my config files with this one junit test file? I have 4 config files in total including the ServiceConfig file, so in the ContextConfiguration should I just list them all out or have a junit test for each one indivually?
What am I supposed to test here? I tried reading this spring guide but I'm not really understand what behavior I should test here....just if something gets autowired successfully?
Should I test all my config files with this one junit test file? I
have 4 config files in total including the ServiceConfig file, so in
the ContextConfiguration should I just list them all out or have a
junit test for each one indivually?
In your test class, #ContextConfiguration must be positioned on the root of the class.
So for testing each configuration, you have to create a test class by Configuration.
What am I supposed to test here? I tried reading this spring guide but
I'm not really understand what behavior I should test here....just if
something gets autowired successfully?
Testing if autowired is successful seems not very useful. It would be as unit test that Spring feature works. If you want to unit test these classes, you should test your own processing. For the moment, you have not really. So, I am not sure that testing them has great value.
Test the intended behaviour of your system or individual units of functionally. As part of this the configs will be tested.
You don't need to make tests to make sure something is wired correctly. That should be implied on the basis that the functionality you are testing works.
You can aggregate multiple configurations into one configuration class using #Import.

Java Spring Derby - datasource specific to unit tests

So, I'm working on a Spring Rest API using JPA and based on an Oracle database.
I have some unit tests, mostly very specific (like regex checks).
I also have some bigger integration tests and at the moment they would interact with the real database.
What I want is to use Derby for the tests and Oracle for the real app.
In an application.properties file, I have the properties for the two datasource scenarios.
I have no other configuration file, no XML file in the entire project
#spring.datasource.url=jdbc:oracle:thin:#1.2.3.4:1521/orcl
#spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#spring.datasource.username=user
#spring.datasource.password=password
spring.datasource.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
spring.datasource.urljdbc:derby:target/database/message;create=true
spring.datasource.username=app
spring.datasource.password=app
also:
#Configuration
#PropertySource(value = { "classpath:application.properties"}, ignoreResourceNotFound = true)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
by manually commenting, uncommenting the right block in the properties file, i can either use derby or the real oracle DB
I would like to make that process automatic by having two "named datasources" that i can use. I'm no Spring expert :-)
What's the easiest/recommended way to achieve this?
Please if you mention some XML, tell me where they should go or how they should be referenced as i don't know about them and there seems to be very conflicting advice online depending on wether you use Spring, EE, different versions of JPA, etc.
Many Thanks!
You can annotate your Tests with the annotation #TestPropertySource which:
can be used to selectively override properties defined in system and
application property sources
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations-spring
So, you can remove the test database properties from application.properties and either put them into a separate file and specify that as a value for #TestPropertySource or you can use the inline mechanism e.g.
#ContextConfiguration
#TestPropertySource(
locations = "/test.db.properties"
)
public class MyDatabaseTest{
}
or
#ContextConfiguration
#TestPropertySource(
properties = {
"spring.datasource.driverClassName=org.apache.derby.jdbc.EmbeddedDriver",
"spring.datasource.urljdbc:derby:target/database/message;create=true",
"spring.datasource.username=app",
"spring.datasource.password=app"
}
)
public class MyDatabaseTest {
}

Categories

Resources