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

如何在Java版AWS Lambda中Mock DynamoDB?

问题原因

你的测试失败是因为Lambda代码中直接在handleRequest方法内创建了DynamoDbEnhancedClient实例(DynamoDbEnhancedClient.create()),Mockito无法拦截静态的create()调用,导致测试时实际发起了对真实DynamoDB服务的请求,从而触发了凭证过期的错误。

解决方案:依赖注入解耦

要正确Mock DynamoDB相关组件,必须将客户端的创建与Lambda业务逻辑解耦,通过构造函数注入的方式传入DynamoDbEnhancedClient,这样测试时可以替换为Mock实例。

步骤1:改造Lambda代码

修改FooLambda类,添加接收DynamoDbEnhancedClient的构造函数,同时保留无参构造(Lambda部署时需要无参构造初始化):

import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

public class FooLambda implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    // 注入的DynamoDB增强客户端
    private final DynamoDbEnhancedClient enhancedClient;

    // 无参构造,用于Lambda部署时初始化(自动创建客户端)
    public FooLambda() {
        this.enhancedClient = DynamoDbEnhancedClient.create();
    }

    // 带参数的构造,用于测试时注入Mock客户端
    public FooLambda(DynamoDbEnhancedClient enhancedClient) {
        this.enhancedClient = enhancedClient;
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
        try {
            DynamoDbTable<FooEntity> fooTable = enhancedClient.table("foo_table", TableSchema.fromBean(FooEntity.class));
            Key fooKey = Key.builder()
                    .partitionValue("foo_key") // 注意原代码拼写错误:foo_ket -> foo_key
                    .build();
            FooEntity fooItem = fooTable.getItem(GetItemEnhancedRequest.builder().key(fooKey).build());
            String barValue = fooItem.getBar();

            // 后续业务逻辑示例
            APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
            response.setStatusCode(200);
            response.setBody(barValue);
            return response;
        } catch (Exception e) {
            System.err.println(e.getMessage());
            APIGatewayProxyResponseEvent errorResponse = new APIGatewayProxyResponseEvent();
            errorResponse.setStatusCode(500);
            errorResponse.setBody("Error: " + e.getMessage());
            return errorResponse;
        }
    }
}

步骤2:编写正确的单元测试

现在可以通过构造函数注入Mock的DynamoDbEnhancedClient,完整Mock整个调用链:

import org.junit.Test;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedRequest;

public class FooLambdaTest {

    @Test
    public void testHandleRequest() {
        // 1. Mock各个组件
        DynamoDbEnhancedClient mockEnhancedClient = mock(DynamoDbEnhancedClient.class);
        DynamoDbTable<FooEntity> mockFooTable = mock(DynamoDbTable.class);
        FooEntity mockFooEntity = mock(FooEntity.class);

        // 2. 配置Mock行为
        when(mockEnhancedClient.table(eq("foo_table"), eq(TableSchema.fromBean(FooEntity.class))))
                .thenReturn(mockFooTable);
        when(mockFooTable.getItem(any(GetItemEnhancedRequest.class))).thenReturn(mockFooEntity);
        when(mockFooEntity.getBar()).thenReturn("test_bar_value");

        // 3. 创建Lambda实例并传入Mock客户端
        FooLambda handler = new FooLambda(mockEnhancedClient);
        APIGatewayProxyRequestEvent input = new APIGatewayProxyRequestEvent();

        // 4. 执行测试
        APIGatewayProxyResponseEvent response = handler.handleRequest(input, null);

        // 5. 断言结果示例
        assert response.getStatusCode() == 200;
        assert response.getBody().equals("test_bar_value");
    }
}

关键注意点

  • 修正原代码中的拼写错误:partitionValue("foo_ket")改为foo_key,避免实际运行时找不到数据。
  • 必须保留Lambda的无参构造,否则AWS Lambda服务无法初始化你的函数。
  • Mock时精确匹配参数(比如表名和Schema),能让测试逻辑更严谨。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 08:20:04