集成测试中Spring Context重复初始化ApplicationProperties Bean问题
问题分析与解决方案
问题原因
你遇到的两个ApplicationProperties Bean实例问题,核心原因是重复引入SpringExtension:
@SpringBootTest注解本身已经集成了SpringExtension,会自动初始化Spring应用上下文并处理所有配置类。- 你的
S3Extension类又额外添加了@ExtendWith(SpringExtension.class),这会触发Spring上下文的重复初始化逻辑,导致ApplicationProperties被注册两次。
解决方案
1. 移除S3Extension上的重复注解
直接删除S3Extension类顶部的@ExtendWith(SpringExtension.class),因为@SpringBootTest已经提供了Spring上下文的支持,不需要在自定义Extension上重复标注。
修改后的S3Extension代码:
public class S3Extension implements BeforeAllCallback, AfterAllCallback, ParameterResolver { private S3Mock s3Mock; private AmazonS3Client s3Client; private ApplicationProperties applicationProperties; @Override public void beforeAll(ExtensionContext context) { applicationProperties = SpringExtension.getApplicationContext(context).getBean(ApplicationProperties.class); s3Mock = new S3Mock.Builder().withPort(9000).withFileBackend("build/s3").build(); s3Mock.start(); s3Client = getClient(); s3Client.createBucket(applicationProperties.getS3().getBucket()); } @Override public void afterAll(ExtensionContext context) { if (s3Mock != null) { s3Mock.shutdown(); } } @Override public boolean supportsParameter( ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().getType() == AmazonS3Client.class; } @Override public Object resolveParameter( ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return s3Client; } public AmazonS3Client getClient() { AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(applicationProperties.getS3().getEndpoint(), "us-west-2"); return (AmazonS3Client) AmazonS3ClientBuilder.standard() .withPathStyleAccessEnabled(true) .withEndpointConfiguration(endpoint) .withCredentials(new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())) .build(); } }
2. 确保ApplicationProperties的正确注册
检查你的ApplicationProperties类及配置,确保只被Spring上下文注册一次:
- 确保
ApplicationProperties类正确标注@ConfigurationProperties:
@ConfigurationProperties(prefix = "application") public class ApplicationProperties { private S3Properties s3; // Getter & Setter public static class S3Properties { private String endpoint; private String bucket; // Getter & Setter } }
- 在Spring启动类或配置类上添加
@EnableConfigurationProperties(ApplicationProperties.class),或者使用@ConfigurationPropertiesScan扫描该类所在包,避免重复注册:
@EnableConfigurationProperties(ApplicationProperties.class) @SpringBootApplication public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
3. 测试类保持原有配置
你的测试类无需修改,@SpringBootTest已经会自动处理Spring上下文,自定义的S3Extension会正常工作:
@ExtendWith({S3Extension.class}) @ActiveProfiles("test") @SpringBootTest() class S3OtherServiceItTest { @Autowired private S3Service s3Service; @MockBean SetupSchedulerJobs setupSchedulerJobs; @MockBean DbStatus dbStatus; @Test public void test(AmazonS3Client client) throws IOException, FileException { File file = new File("test.txt"); Files.write(file.toPath(), "contents".getBytes()); s3Service.uploadLocalFile(file.getPath(), "another/file/name"); client.listObjects("tkgpdf-bucket").getObjectSummaries().forEach(System.out::println); } }
内容的提问来源于stack exchange,提问作者EdgyCoder
相关产品推荐
相关产品推荐

