Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Here is my
DatasourceConfiguration.java
file. It's a configuration file, to set up the Hikari config and the QuartzDatasource is built based on the Hikari config.
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DatasourceConfiguration {
@Value("${spring.datasource.scheduler.jdbcUrl}")
private String jdbcUrl;
@Value("${spring.datasource.scheduler.username}")
private String userName;
@Value("${spring.datasource.scheduler.driverClassname}")
private String driverClassname;
@Value("${spring.datasource.scheduler.password}")
private String password;
@Bean
public HikariConfig hikariConfig() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassname);
hikariConfig.setJdbcUrl(jdbcUrl);
hikariConfig.setUsername(userName);
hikariConfig.setPassword(password);
return hikariConfig;
@Bean(name = "quartzDataSource")
@QuartzDataSource
public DataSource dataSource() {
return new HikariDataSource(hikariConfig());
And here is my DatasourceConfigurationTest.java
file:
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.ApplicationContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.sql.DataSource;
import java.sql.SQLException;
import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@TestPropertySource(locations = "classpath:application.properties")
@ContextConfiguration(classes = DatasourceConfiguration.class)
class DatasourceConfigurationTest {
@Autowired
private ApplicationContext context;
@Test
void validateConfiguration() throws SQLException {
assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(1);
HikariDataSource dataSource = this.context.getBean(HikariDataSource.class);
assertThat(dataSource.getConnection().getMetaData().getURL()).isEqualTo("jdbc:h2:mem:simple");
assertThat(dataSource.getMaximumPoolSize()).isEqualTo(42);
When I run the Unit Test, I recognized that it failed to load ApplicationContext.
Here is the log:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getHikariConfig' defined in com.gm.gcc.vas.utility.messageretry.config.DatasourceConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariConfig]: Factory method 'getHikariConfig' threw exception; nested exception is java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariConfig]: Factory method 'getHikariConfig' threw exception; nested exception is java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 87 common frames omitted
Caused by: java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:491)
at com.gm.gcc.vas.utility.messageretry.config.DatasourceConfiguration.getHikariConfig(DatasourceConfiguration.java:37)
... 88 common frames omitted
Here is the properties file:
spring.datasource.scheduler.driverClassname=test-driver-classname
spring.datasource.scheduler.jdbcUrl=jdbc:test-url
spring.datasource.scheduler.password=test-password
spring.datasource.scheduler.username=test-username
As my understanding, when trying to create a connection, it failed because of dummy values.
I just wonder if my approach to do the unit test is correct or not, if yes, how can I fix the ApplicationContext error? Else, what is the correct way to ensure 100% converage.
If you want to execute integration tests, you need a running DB instance to which Spring can connect. Your test is not a unit test as it is extended with the SpringExtension
.
You could use an embedded H2 database for your tests, you would then need to add H2 as test dependency in your pom.xml
:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
In your application-test.properties
:
spring.datasource.scheduler.driverClassname=org.h2.Driver
spring.datasource.scheduler.jdbcUrl=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
spring.datasource.scheduler.password=sa
spring.datasource.scheduler.username=sa
In order to have the application-test.properties
loaded for your test you should either replace the @TestPropertySource(locations = "classpath:application.properties")
with @ActiveProfiles("test")
or reference the file @TestPropertySource(locations = "classpath:application-test.properties")
.
Another good alternative would be using the Testcontainers
project which allows you to run the database that you use in production (like Postgres or MySQL) in a docker container. Here is a good tutorial by Baeldung.
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.