Quarkus DynamoDB测试初始化:LocalStack表创建与清理方案咨询
在Quarkus测试中用LocalStack管理DynamoDB表的可行方案
针对你遇到的QuarkusTestResourceLifecycleManager无法使用CDI注入、客户端读取不到配置的问题,这里提供两种实用解决方案:
方案一:Testcontainers LocalStack + Quarkus测试扩展(推荐)
这个方案无需手动管理LocalStack生命周期,Quarkus会自动配置DynamoDB客户端,CDI注入正常可用。
步骤1:添加依赖
Maven项目在pom.xml中添加:
<dependency> <groupId>org.testcontainers</groupId> <artifactId>localstack</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-testcontainers</artifactId> <scope>test</scope> </dependency>
步骤2:配置测试环境
在src/test/resources/application.properties中添加:
# 自动引用Testcontainers暴露的LocalStack环境变量 quarkus.dynamodb.endpoint-override=${localstack.dynamodb.url} quarkus.dynamodb.aws.region=${localstack.region} quarkus.dynamodb.aws.credentials.type=static quarkus.dynamodb.aws.credentials.access-key=test quarkus.dynamodb.aws.credentials.secret-key=test
步骤3:编写测试类
import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.testcontainers.LocalStackContainer; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import jakarta.inject.Inject; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.testcontainers.containers.localstack.LocalStackContainer.Service.DYNAMODB; @QuarkusTest @QuarkusTestResource(value = LocalStackContainer.class, restrictToAnnotatedClass = true) public class DynamoDBIntegrationTest { @Inject DynamoDbEnhancedClient enhancedClient; private static final String TEST_TABLE = "user-profiles"; @BeforeEach void createTestTable() { // 假设你有对应的实体类UserProfile enhancedClient.table(TEST_TABLE, TableSchema.fromBean(UserProfile.class)) .createTable(); } @AfterEach void deleteTestTable() { enhancedClient.table(TEST_TABLE, TableSchema.fromBean(UserProfile.class)) .deleteTable(); } @Test void testDynamoDBOperations() { // 这里编写你的业务测试逻辑 } }
方案二:自定义QuarkusTestResourceLifecycleManager
如果需要完全自定义资源生命周期,可以手动构建客户端并读取配置,同时将配置传递给Quarkus应用。
自定义TestResource实现
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import java.net.URI; import java.util.Map; public class DynamoDBTestResource implements QuarkusTestResourceLifecycleManager { private DynamoDbEnhancedClient enhancedClient; private static final String TEST_TABLE = "order-records"; @Override public Map<String, String> start() { // 读取测试配置(也可从QuarkusConfigProvider获取) String localStackEndpoint = "http://localhost:4566"; String region = "us-east-1"; String accessKey = "test"; String secretKey = "test"; // 构建DynamoDB客户端 DynamoDbClient client = DynamoDbClient.builder() .endpointOverride(URI.create(localStackEndpoint)) .region(Region.of(region)) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create(accessKey, secretKey))) .build(); enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(client) .build(); // 预创建测试表 enhancedClient.table(TEST_TABLE, TableSchema.fromBean(OrderRecord.class)) .createTable(); // 将配置传递给Quarkus应用,确保应用内客户端使用同一配置 return Map.of( "quarkus.dynamodb.endpoint-override", localStackEndpoint, "quarkus.dynamodb.aws.region", region, "quarkus.dynamodb.aws.credentials.access-key", accessKey, "quarkus.dynamodb.aws.credentials.secret-key", secretKey ); } @Override public void stop() { if (enhancedClient != null) { // 清理测试表 enhancedClient.table(TEST_TABLE, TableSchema.fromBean(OrderRecord.class)) .deleteTable(); enhancedClient.close(); } } }
在测试类中使用自定义资源
import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; @QuarkusTest @QuarkusTestResource(DynamoDBTestResource.class) public class DynamoDBManualTest { @Inject DynamoDbEnhancedClient enhancedClient; @Test void testCustomResourceSetup() { // 测试逻辑 } }
核心注意事项
- QuarkusTestResourceLifecycleManager的初始化早于CDI容器,因此无法在其中使用CDI注入,必须手动构建客户端
- LocalStack默认使用
test/test作为访问凭证,测试环境配置必须与之匹配,否则会出现"table not found"或权限错误 - 使用Testcontainers时无需硬编码LocalStack端口,通过环境变量引用即可避免端口冲突
内容的提问来源于stack exchange,提问作者Nicklas Karlsson
相关产品推荐
相关产品推荐

