You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成测试中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:23:27