添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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.

We use this implementation but I want to note that H2 is not 1:1 with Oracle syntax. Just a note that some queries for Oracle when ran against this H2 instance may break giving false negatives in unit tests. – Poken1151 Mar 13 at 20:47

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.