Spring Boot 2.6.4 -> 2.6.6:记录模拟异常时 Logback 中出现奇怪的 NullPointerException
Spring Boot 2.6.4 -> 2.6.6 : strange NullPointerException within Logback when logging a mock Exception
从 Spring Boot 2.6.4 升级到 2.6.6 时,我的一项测试(用 Kotlin 编写)失败了:
@Test
fun shouldLogProperMessageIfNotAbleToHitAPI() {
val configValidator = ConfigValidator(GitHubCrawlerProperties(SourceControlConfig(url = "someIncorrectURL",organizationName="someOrg")),mockRemoteSourceControl)
`when`(mockRemoteSourceControl.validateRemoteConfig("someOrg")).thenThrow(NoReachableRepositories("problem !",mock(Exception::class.java)))
val validationErrors=configValidator.getValidationErrors()
assertThat(validationErrors).hasSize(1);
}
构建通过 Spring Boot 2.6.4。当我 运行 在我的 IDE 中单独测试时,它在 Spring Boot 2.6.6 中工作,但在 Maven 构建过程中失败。
stacktrace 默认情况下不显示,但在用 try/catch 包围调用后,我能够得到它,它指向 Logback :
java.lang.NullPointerException: null
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:99)
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:89)
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:62)
at ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:119)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.error(Logger.java:538)
at com.societegenerale.githubcrawler.ConfigValidator.getValidationErrors(ConfigValidator.kt:48)
Logback 版本似乎没有变化,我仍然得到 v 1.2.11 。
查看 Logback 源代码,在 ThrowableProxy 中:
if (GET_SUPPRESSED_METHOD != null) {
// this will only execute on Java 7
Throwable[] throwableSuppressed = extractSupressedThrowables(throwable);
if (throwableSuppressed.length > 0) {
List<ThrowableProxy> suppressedList = new ArrayList<ThrowableProxy>(throwableSuppressed.length);
for (Throwable sup : throwableSuppressed) {
...
注意:我使用 Java 11 进行构建,因此 Logback 源代码中的注释 this will only execute on Java 7
似乎是错误的。
好像throwableSuppressed
是null,调用throwableSuppressed.size
的时候得到NPE
如果我没有在 NoReachableRepositories("problem !",mock(Exception::class.java))
中使用模拟,而是使用 NoReachableRepositories("problem !",Exception())
,则测试通过
我意识到使用真正的异常可能比模拟更好,所以我的问题以某种方式解决了(在这上面花了 2 个小时之后..)。
不过,我很好奇:升级到 Spring Boot 2.6.6 后可能会导致此问题,这应该是一个小改动?
从 Spring Boot 2.6.4 升级到 2.6.6 时,我的一项测试(用 Kotlin 编写)失败了:
@Test
fun shouldLogProperMessageIfNotAbleToHitAPI() {
val configValidator = ConfigValidator(GitHubCrawlerProperties(SourceControlConfig(url = "someIncorrectURL",organizationName="someOrg")),mockRemoteSourceControl)
`when`(mockRemoteSourceControl.validateRemoteConfig("someOrg")).thenThrow(NoReachableRepositories("problem !",mock(Exception::class.java)))
val validationErrors=configValidator.getValidationErrors()
assertThat(validationErrors).hasSize(1);
}
构建通过 Spring Boot 2.6.4。当我 运行 在我的 IDE 中单独测试时,它在 Spring Boot 2.6.6 中工作,但在 Maven 构建过程中失败。
stacktrace 默认情况下不显示,但在用 try/catch 包围调用后,我能够得到它,它指向 Logback :
java.lang.NullPointerException: null
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:99)
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:89)
at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:62)
at ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:119)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.error(Logger.java:538)
at com.societegenerale.githubcrawler.ConfigValidator.getValidationErrors(ConfigValidator.kt:48)
Logback 版本似乎没有变化,我仍然得到 v 1.2.11 。
查看 Logback 源代码,在 ThrowableProxy 中:
if (GET_SUPPRESSED_METHOD != null) {
// this will only execute on Java 7
Throwable[] throwableSuppressed = extractSupressedThrowables(throwable);
if (throwableSuppressed.length > 0) {
List<ThrowableProxy> suppressedList = new ArrayList<ThrowableProxy>(throwableSuppressed.length);
for (Throwable sup : throwableSuppressed) {
...
注意:我使用 Java 11 进行构建,因此 Logback 源代码中的注释 this will only execute on Java 7
似乎是错误的。
好像throwableSuppressed
是null,调用throwableSuppressed.size
的时候得到NPE
如果我没有在 NoReachableRepositories("problem !",mock(Exception::class.java))
中使用模拟,而是使用 NoReachableRepositories("problem !",Exception())
我意识到使用真正的异常可能比模拟更好,所以我的问题以某种方式解决了(在这上面花了 2 个小时之后..)。
不过,我很好奇:升级到 Spring Boot 2.6.6 后可能会导致此问题,这应该是一个小改动?