test(storage): cover deferred S3 bucket verification

This commit is contained in:
wowo-zZ 2026-04-12 15:10:54 +08:00
parent 8e57595633
commit 40f0b20c86

View file

@ -2,12 +2,32 @@ package com.iflytek.skillhub.storage;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.CreateBucketResponse;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import java.io.ByteArrayInputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
class S3StorageServiceTest {
@ -27,6 +47,63 @@ class S3StorageServiceTest {
assertThat(presignedUrl.getPath()).isEqualTo("/artifacts/package.tgz");
}
@Test
void initShouldNotProbeBucketWhenAutoCreateIsDisabled() {
S3Client client = mock(S3Client.class);
S3Presigner presigner = mock(S3Presigner.class);
TestableS3StorageService service = new TestableS3StorageService(properties(false), client, presigner);
service.init();
verifyNoInteractions(client);
}
@Test
void putObjectShouldSkipBucketProbeWhenAutoCreateIsDisabled() {
S3Client client = mock(S3Client.class);
S3Presigner presigner = mock(S3Presigner.class);
when(client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
.thenReturn(PutObjectResponse.builder().eTag("etag").build());
TestableS3StorageService service = new TestableS3StorageService(properties(false), client, presigner);
service.init();
byte[] content = "hello".getBytes(StandardCharsets.UTF_8);
service.putObject("packages/demo.zip", new ByteArrayInputStream(content), content.length, "application/zip");
verify(client, never()).headBucket(any(HeadBucketRequest.class));
verify(client, never()).createBucket(any(CreateBucketRequest.class));
verify(client).putObject(any(PutObjectRequest.class), any(RequestBody.class));
}
@Test
void putObjectShouldCreateBucketOnlyOnceWhenAutoCreateIsEnabled() {
S3Client client = mock(S3Client.class);
S3Presigner presigner = mock(S3Presigner.class);
doThrow(NoSuchBucketException.builder().message("missing").build())
.when(client).headBucket(any(HeadBucketRequest.class));
when(client.createBucket(any(CreateBucketRequest.class)))
.thenReturn(CreateBucketResponse.builder().build());
when(client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
.thenReturn(PutObjectResponse.builder().eTag("etag").build());
TestableS3StorageService service = new TestableS3StorageService(properties(true), client, presigner);
service.init();
byte[] content = "hello".getBytes(StandardCharsets.UTF_8);
service.putObject("packages/demo-1.zip", new ByteArrayInputStream(content), content.length, "application/zip");
service.putObject("packages/demo-2.zip", new ByteArrayInputStream(content), content.length, "application/zip");
verify(client, times(1)).headBucket(any(HeadBucketRequest.class));
verify(client, times(1)).createBucket(any(CreateBucketRequest.class));
verify(client, times(2)).putObject(any(PutObjectRequest.class), any(RequestBody.class));
}
private S3StorageProperties properties(boolean autoCreateBucket) {
S3StorageProperties properties = createProperties(true);
properties.setBucket("skillhub");
properties.setAutoCreateBucket(autoCreateBucket);
return properties;
}
private URI presignGetObjectUrl(boolean forcePathStyle) {
S3StorageService storageService = new S3StorageService(createProperties(forcePathStyle));
try (var presigner = storageService.buildPresigner()) {
@ -53,4 +130,25 @@ class S3StorageServiceTest {
properties.setForcePathStyle(forcePathStyle);
return properties;
}
private static final class TestableS3StorageService extends S3StorageService {
private final S3Client client;
private final S3Presigner presigner;
private TestableS3StorageService(S3StorageProperties properties, S3Client client, S3Presigner presigner) {
super(properties);
this.client = client;
this.presigner = presigner;
}
@Override
protected S3Client buildS3Client(ApacheHttpClient.Builder httpClientBuilder) {
return client;
}
@Override
S3Presigner buildPresigner() {
return presigner;
}
}
}