简体   繁体   中英

Spring boot gradle build failing due to exception "HikariPool$PoolInitializationException" in unit test

Test cases are running fine when we run them individually it only gives this exception when we are trying to create a build.

This is the exception we are getting for every test case.

StudentReportControllerTest > testSubmittedPaperController() FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
        Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:800
            Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:658
                Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:185
        Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:800

                    Caused by: com.zaxxer.hikari.pool.HikariPool$PoolInitializationException at HikariPool.java:596
                        Caused by: org.postgresql.util.PSQLException at QueryExecutorImpl.java:2552
            Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:658

                Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:185

                    Caused by: com.zaxxer.hikari.pool.HikariPool$PoolInitializationException at HikariPool.java:596

                        Caused by: org.postgresql.util.PSQLException at QueryExecutorImpl.java:2552

We are using primary and replica database configuration and once we implemented that this issue occurred.

@Aspect
@Component
@Order(0)
public class ReadOnlyRouteInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(ReadOnlyRouteInterceptor.class);

    @Around("@annotation(transactional)")
    public Object proceed(ProceedingJoinPoint proceedingJoinPoint, Transactional transactional) throws Throwable {
        try {
            if (transactional.readOnly()) {
                RoutingDataSource.setReplicaRoute();
                logger.info("Routing database call to the read replica");
            }
            return proceedingJoinPoint.proceed();
        } finally {
            RoutingDataSource.clearReplicaRoute();
        }
    }
}
public class RoutingDataSource extends AbstractRoutingDataSource {

    private static final ThreadLocal<Route> routeContext = new ThreadLocal<>();

    public enum Route {
        PRIMARY, REPLICA
    }

    public static void clearReplicaRoute() {
        routeContext.remove();
    }

    public static void setReplicaRoute() {
        routeContext.set(Route.REPLICA);
    }

    @Override
    public Object determineCurrentLookupKey() {
        return routeContext.get();
    }
}
@Configuration
public class DataSourceConfig {

    private static final String PRIMARY_DATASOURCE_PREFIX = "spring.primary.datasource";
    private static final String REPLICA_DATASOURCE_PREFIX = "spring.replica.datasource";

    @Autowired
    private Environment environment;

    @Bean
    @Primary
    public DataSource dataSource() {
        final RoutingDataSource routingDataSource = new RoutingDataSource();

        final DataSource primaryDataSource = buildDataSource("PrimaryHikariPool", PRIMARY_DATASOURCE_PREFIX);
        final DataSource replicaDataSource = buildDataSource("ReplicaHikariPool", REPLICA_DATASOURCE_PREFIX);

        final Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(RoutingDataSource.Route.PRIMARY, primaryDataSource);
        targetDataSources.put(RoutingDataSource.Route.REPLICA, replicaDataSource);

        routingDataSource.setTargetDataSources(targetDataSources);
        routingDataSource.setDefaultTargetDataSource(primaryDataSource);

        return routingDataSource;
    }

    private DataSource buildDataSource(String poolName, String dataSourcePrefix) {
        final HikariConfig hikariConfig = new HikariConfig();

        hikariConfig.setPoolName(poolName);
        hikariConfig.setJdbcUrl(environment.getProperty(String.format("%s.url", dataSourcePrefix)));
        hikariConfig.setUsername(environment.getProperty(String.format("%s.username", dataSourcePrefix)));
        hikariConfig.setPassword(environment.getProperty(String.format("%s.password", dataSourcePrefix)));
        hikariConfig.setDriverClassName(environment.getProperty(String.format("%s.driver", dataSourcePrefix)));

        return new HikariDataSource(hikariConfig);
    }
}

My build.gradle

plugins {
    id 'org.springframework.boot' version '2.5.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id 'jacoco'
    id 'org.sonarqube' version '3.0'
}

group = 'com.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}
ext {
    set('springCloudVersion', "2020.0.2")
}
dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.9'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.5.2'
    implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
    implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
    implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '2.6.1'
    implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'
    implementation group: 'commons-io', name: 'commons-io', version: '2.6'
    implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.1000')
    implementation 'com.amazonaws:aws-java-sdk-s3'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'org.postgresql:postgresql'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-config'
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client'
}

test {
    useJUnitPlatform()
    finalizedBy jacocoTestReport
}
jacocoTestReport {
    dependsOn test
    reports {
        //xml.required false
//      csv.enabled false
        html.enabled true
        xml.enabled false
        csv.enabled false
        html.enabled true
    }
    afterEvaluate {
        getClassDirectories().setFrom(classDirectories.files.collect {
            fileTree(dir: it,
                    exclude: [
                            '**/entity/**',
                            '**/request/**',
                            '**/dto/**',
                            '**/config/**',
                            '**/interceptor/**',
                            '**/mapper/**',
                            '**/utils/**',
                            '**/enums/**',
                            '**/response/**',
                            '**/filters/**',
                            '**/constants/**',
                            '**/exception/**',
                            '**/log/**',
                            '**/StudentTestReportApplication.class',
                    ]
            )
        })
    }
}

One of my test class

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
class StudentReportControllerTest {
    @Autowired
    StudentReportController studentReportController;

    @MockBean
    PaperReportStudentService paperReportStudentService;

    @MockBean
    PaperDetailStudentService paperDetailStudentService;

    @Autowired
    TeacherReportController teacherReportController;

    @MockBean
    PaperDetailTeacherService paperDetailTeacherService;

    @MockBean
    QuestionWiseReportStudentService questionWiseReportStudentService;

    @Autowired
    private MockMvc mockMvc;

    protected String mapToJson(Object obj) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(obj);
    }

    @Test
    void getTeacherAssignmentsNegativeTest() throws Exception
        String inputJson = mapToJson(new TeacherRequest());
        final MockHttpServletResponse response =
                mockMvc
                        .perform(
                                post(REPORT_API + GET_TEACHER_ASSIGNMENTS)
                                        .content(inputJson)
                                        .contentType(MediaType.APPLICATION_JSON)
                                        .accept(MediaType.APPLICATION_JSON))
                        .andReturn()
                        .getResponse();

        assertThat(new JSONObject(response.getContentAsString()).get("status")).isEqualTo(404);
        assertThat(new JSONObject(response.getContentAsString()).get("message")).isEqualTo(Constants.RECORD_NOT_FOUND);
    }

This is our property file

spring.cloud.config.import-check.enabled=false
spring.jpa.show-sql=true
spring.datasource.initialization-mode=always
spring.datasource.initialize=true
spring.datasource.continue-on-error=true
spring.datasource.hikari.connection-timeout=10000
spring.datasource.hikari.minimum-idle=1
spring.datasource.hikari.maximum-pool-size=1
spring.redis.timeout=2000
spring.jackson.property-naming-strategy=SNAKE_CASE
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=Asia/Kolkata
spring.data.redis.timeout=3000
eureka.client.enabled=false
#
spring.primary.datasource.password=postgres
spring.primary.datasource.username=postgres
spring.primary.datasource.driver=org.postgresql.Driver
spring.primary.datasource.url=jdbc:postgresql://127.0.0.1/master?stringtype=unspecified
#
spring.replica.datasource.password=postgres
spring.replica.datasource.username=postgres
spring.replica.datasource.driver=org.postgresql.Driver
spring.replica.datasource.url=jdbc:postgresql://127.0.0.1/replica?stringtype=unspecified

I have resolved this issue now. To get a better exception detail I have tried "Gradle check" and then I found out that this issue was due to limited connection size on our db and We are creating DB connections unknowingly in our unit test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM