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
相关产品推荐
相关产品推荐

