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

SpringBootTest整合Testcontainers与fake-gcs-server遇凭证错误求助

解决Spring Boot测试中fake-gcs-server的凭证错误问题

问题根源

你遇到的Application Default Credentials are not available错误,并非来自测试代码中手动创建的Storage实例,而是Spring Boot上下文初始化时,GCP相关自动配置类会尝试自动创建Storage Bean并加载默认凭证,这和你手动配置的无凭证实例冲突——因为@SpringBootTest会启动完整的Spring上下文,触发了自动配置逻辑。

解决方案

1. 排除GCS自动配置类

在@SpringBootTest注解中排除GCP存储的自动配置类,阻止Spring自动创建Storage Bean:

@SpringBootTest(exclude = {GcpStorageAutoConfiguration.class, GcpAutoConfiguration.class})

2. 优化StorageOptions配置(适配fake-gcs-server)

部分版本的GCS客户端需要启用路径样式访问才能正常对接fake-gcs-server,可在配置中添加该设置:

StorageOptions storageOps = StorageOptions.newBuilder()
        .setCredentials(NoCredentials.getInstance())
        .setHost("http://" + gcsFakeContainer.getHost() + ":" + mappedPort)
        .setProjectId("TEST_LOCAL")
        .setPathStyleAccess(true) // 启用路径样式访问,适配fake-gcs-server
        .build();

3. 修改后的完整测试类示例

@SpringBootTest(exclude = {GcpStorageAutoConfiguration.class, GcpAutoConfiguration.class})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@Testcontainers
class GPSStorageTest {

    private static final String BUCKET_NAME = "BUCKET_TEST";
    private static final Integer INTERNAL_PORT = 8888;
    protected static Storage storage = null;

    @Container
    private static final GenericContainer<?> gcsFakeContainer =
            new GenericContainer<>(DockerImageName.parse("fsouza/fake-gcs-server:latest"))
                    .withCommand("-port", INTERNAL_PORT.toString(), "-scheme", "http")
                    .withExposedPorts(8888)
                    .waitingFor(Wait.forHttp("/").forStatusCode(404))
                    .withReuse(true);

    @BeforeAll
    public static void setup() {
        int mappedPort = gcsFakeContainer.getMappedPort(INTERNAL_PORT);
        StorageOptions storageOps = StorageOptions.newBuilder()
                .setCredentials(NoCredentials.getInstance())
                .setHost("http://" + gcsFakeContainer.getHost() + ":" + mappedPort)
                .setProjectId("TEST_LOCAL")
                .setPathStyleAccess(true)
                .build();

        storage = storageOps.getService();
    }

    @Test
    @Order(1)
    public void testCreateBucket() {
        createBucket();
        Assertions.assertTrue(checkBucketExists());
    }

    @Test
    @Order(2)
    public void testIfFileWritten() {
        String filename = "test.txt";
        Bucket bucket = storage.get(BUCKET_NAME);
        bucket.create(filename, "Hello, World!".getBytes(StandardCharsets.UTF_8));
        Assertions.assertTrue(fileExists(filename));
    }

    private boolean fileExists(String filename) {
        return storage.get(BUCKET_NAME, filename) != null;
    }

    private void createBucket() {
        try {
            storage.create(BucketInfo.of(BUCKET_NAME));
        } catch (Exception ex) {
            System.err.println("Error creating bucket");
            ex.printStackTrace();
        }
    }

    private boolean checkBucketExists() {
        return storage.get(BUCKET_NAME, Storage.BucketGetOption.fields()) != null;
    }
}

额外检查点

  • 确认项目依赖中是否存在spring-cloud-gcp-storage或其他GCP存储相关依赖,这类依赖会触发自动配置,排除对应配置类是解决问题的核心。
  • 验证fake-gcs-server容器是否正常启动,测试中waitingFor(Wait.forHttp("/").forStatusCode(404))的检查逻辑是合理的——fake-gcs-server根路径本身没有资源,返回404属于正常状态。

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:10:47