【发布时间】:2022-02-07 10:27:05
【问题描述】:
当我们单独运行测试用例时,它们运行良好,只有在我们尝试创建构建时才会出现此异常。
这是我们为每个测试用例得到的例外。
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
我们正在使用主数据库和副本数据库配置,一旦我们实施,就会发生此问题。
@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);
}
}
我的 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',
]
)
})
}
}
我的一个测试课
@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);
}
这是我们的属性文件
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
【问题讨论】:
-
我现在已经解决了这个问题。为了获得更好的异常细节,我尝试了“Gradle check”,然后我发现这个问题是由于我们的数据库上的连接大小有限,我们在单元测试中不知不觉地创建了数据库连接。
标签: java spring-boot gradle build hikaricp