gpt4 book ai didi

java - 使用SpringBootTest和Autowired注解时LogCaptor捕获失败

转载 作者:行者123 更新时间:2023-12-03 08:13:12 25 4
gpt4 key购买 nike

在使用注释 SpringBootTest 和 Autowiring 服务时,我在捕获日志的集成测试中出现了奇怪的行为。我用LogCaptor捕获日志。

通过特定的设置,我无法捕获日志,并且我无法理解为什么会发生这种情况。我不确定我是否错过了 Spring Boot 测试配置的某些内容,或者是否是其他内容。

所以我们假设有一个 FooService:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class FooService {

private static final Logger LOGGER = LoggerFactory.getLogger(FooService.class);

public String hello() {
LOGGER.error("Expected error message");
return "hello";
}

}

以及集成测试:

这次失败了

import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class AppIT {

private static final LogCaptor logcaptor = LogCaptor.forClass(FooService.class);

@Autowired
private FooService fooService;

@Test
void testMethod() {
fooService.hello();
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}

}

上面的测试将失败,但是当我不使用 SpringBootTest 注释而仅在测试方法中使用初始值 FooService 时,它​​会通过:

这些全部通过

import nl.altindag.log.LogCaptor;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class AppIT {

private static final LogCaptor logcaptor = LogCaptor.forClass(FooService.class);

@Test
void testMethod() {
new FooService().hello();
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}

}
import nl.altindag.log.LogCaptor;
import nl.altindag.server.service.FooService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.PostConstruct;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class AppIT {

private FooService fooService;
private LogCaptor logcaptor;

@Autowired
AppIT(FooService fooService) {
this.fooService = fooService;
}

@PostConstruct
void init() {
this.logcaptor = LogCaptor.forClass(FooService.class);
}

@Test
void testMethod() {
fooService.hello();
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}

}
import nl.altindag.log.LogCaptor;
import nl.altindag.server.service.FooService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class AppIT {

private FooService fooService;
private LogCaptor logcaptor;

@Autowired
AppIT(FooService fooService) {
this.fooService = fooService;
this.logcaptor = LogCaptor.forClass(FooService.class);
}

@Test
void testMethod() {
fooService.hello();
assertThat(logcaptor.getErrorLogs()).containsExactly("Expected error message");
}

}

使用了以下库:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.6.1</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>logcaptor</artifactId>
<version>2.7.2</version>
<scope>test</scope>
</dependency>

我尝试在测试和其他设置中使用后构造,例如使用构造函数并使用自动连线对其进行注释并将 logcaptor 设置放在那里,这些设置确实有效,但我不明白为什么上面的具体情况会失败。有人知道可能是什么问题吗?

最佳答案

失败测试的问题在于类变量logcaptor是在创建测试应用程序上下文之前创建的。在测试应用程序上下文的引导过程中,Spring Boot 将从头开始完全配置 logback。这会导致 LogCaptor::forClass 中添加的附加程序丢失。

在成功的 @SpringBootTest 测试中,追加器是在上下文生命周期的较晚阶段添加的。

当您采取两个通过的 @SpringBootTest 测试中的任何一个并将它们一起执行时,只要不首先执行失败的测试,就可以使测试通过。这是因为 Spring 测试框架不会引导新的上下文,而是重用第一个运行的测试的上下文。如果您使用 @DirtiesContext(classMode = ClassMode.BEFORE_CLASS) 注释其类,则测试可能会再次失败,因为在类变量 logcaptor 之后将再次创建一个新的上下文> 已分配。

恐怕对此我们无能为力。 Spring Boot 团队在 github 上的这条评论是关于类似的问题:https://github.com/spring-projects/spring-boot/issues/19323#issuecomment-563166919

关于java - 使用SpringBootTest和Autowired注解时LogCaptor捕获失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70259059/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com