Recently, we had to write integration tests because a connection with the database was required in almost all aspects of our business logic. Writing only unit tests without a DB connection didn’t make much sense – we were only able to check if the API returns a proper error message in cases like no records or unsuccessful authentication. Therefore, it was necessary to test using the database.
It’s important to test the DB connection without changing the structure of the production database – but how can this be done? The answer is quite simple – use two databases – the production one and the test one.
Our project is written in Java using the Spring 4 platform.
First, I created a test database using dump from the original one.
I prepared scripts to create, recreate and drop this database as needed, which were added to Makefile.
Now, how can you force the application to use the regular database in all cases except test, where it should use the test database? You just have to swap the database.properties file.
My original database.properties looked like this:
datasource.driver-class-name=org.postgresql.Driver
datasource.url=jdbc:postgresql://127.0.0.1:5432/my_database
datasource.username=my_username
datasource.password=my_pass
I added a database-test.properties file:
datasource.driver-class-name=org.postgresql.Driver
datasource.url=jdbc:postgresql://127.0.0.1:5432/test_db
datasource.username=test_username
datasource.password=test_pass
We can use a different property (not only for the database, but for everything else as well) using a Spring annotation from spring-test dependency.
The test class should have 3 annotations:@RunWith (SpringJUnit4ClassRunner.class)
– Indicates that the class should use Spring’s JUnit facilities@ContextConfiguration (Application.class)
– Indicates ApplicationContext.
My Application.class looks like this:
@Configuration
@PropertySources({
@PropertySource("classpath:database.properties"),
@PropertySource("classpath:application.properties")
})
@ComponentScan
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
And to override original properties you should just use @TestPropertySource annotation. It is a class-level annotation, configuring the location of property files and inlined properties which should be added to set of PropertySources in the Environment. The test property sources have a higher priority than those added declaratively or programmatically using @PropertySource annotation. It works fine to override single classes and make them use different property sources than in the rest of application.
So, the entire test looked more less like this:
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource("classpath:database-test.properties")
@ContextConfiguration(classes = Application.class)
public class SomethingIntegrationTest {
@Autowired
private SomeRepo repo;
@Test
public void should_return_proper_something_list_size() {
List allSomethings = repo.getAllSomethings();
assertThat("Somethings list should return 7 records", allSomethings.size(), is(7));
}
}
I added this dependency to pom.xml file:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
We’re skilled in Java programming, but we’re also experts in creating software in many different languages… if you’re interested, take a look at our services.
author: Iga Stępniak