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

Mock类方法后仍出现DynamoDB凭证错误,求排查方案

问题描述

我在测试HouseManager类的getHouseFullInfo方法时遇到了异常:该方法依赖DynamoDBClient和DynamoDBDocumentClient从DynamoDB获取数据,我已Mock相关依赖,但运行测试时仍抛出「无效或无凭证」错误——按Mock逻辑本不该触发这个问题。

其他文件中使用相同依赖实现的函数测试均正常,但针对HouseManager尝试多种Mock方式均失败。我的测试代码如下:

import * as AWSMock from 'aws-sdk-mock';
import * as AWS from 'aws-sdk';
import { HouseManager } from '../../lambda/house_manager';
import { Logger } from '@aws-lambda-powertools/logger';
import { QueryInput, DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';

// Assuming AWSMock has a way to mock AWS SDK v3 or using jest for mocking
jest.mock('@aws-sdk/client-dynamodb');
jest.mock('@aws-lambda-powertools/logger');
jest.mock('@aws-sdk/lib-dynamodb')


const loggerMock = { info: jest.fn(), error: jest.fn() } as unknown as Logger;
new Logger();


describe('HouseManager', () => {
    let houseManager: HouseManager;
    let ddb: DynamoDBDocumentClient;

    beforeAll(() => {
        const ddbClient = new DynamoDBClient({
            region: 'us-east-1', // Choose an appropriate region
            credentials: {
                accessKeyId: 'testing',
                secretAccessKey: 'testing',
                sessionToken: 'testing'
            }
        });
        ddb = DynamoDBDocumentClient.from(ddbClient, {
            // Automatically remove undefined values
            marshallOptions: {
                removeUndefinedValues: true
            },
        });

        // Set the AWS SDK instance for mocking
        AWSMock.setSDKInstance(AWS);

        // Set the AWS Mock Response
        const mockResponse = {
            Items: [{
                PK: `HOUSE#aa231eb4-2927-46f4-a625-f6167ebc019c`,
                data: {
                    id: 'aa231eb4-2927-46f4-a625-f6167ebc019c',
                    name: "Jest Test House",
                    description: "This an automated test house for JEST.",
                    owner: "JEST-0001",
                    priceDetails: {
                        dailyPriceAvg: 300,
                        guestFee: 50,
                        petFee: 20,
                        priceCalendar: "c_f5f4ec60eb80b6b4c4824eeaa569da58f99eaa103cc0b0555ade5ae7fd746a0d@group.calendar.google.com"
                    },
                    location: {
                        active: true,
                        cityId: "BSB",
                        cityName: "Brasília",
                        countryId: "BR",
                        countryName: "Brasil",
                        stateId: "DF",
                        stateName: "Distrito Federal"
                    },
                    active: true
                },
                entity: 'HOUSE'
            }]
        };
        AWSMock.mock('DynamoDB.DocumentClient', 'query', (params: QueryInput, callback: any) => {
            callback(null, mockResponse);
        });
    });

    afterAll(() => {
        AWSMock.restore();
    });
    beforeEach(() => {
        houseManager = new HouseManager();
        jest.clearAllMocks();
    });

    describe('getHouseFullInfo', () => {
        it('should call the logger info method', () => {
            loggerMock.info('test');
            expect(loggerMock.info).toHaveBeenCalledWith('test');
        });

        it('successfully retrieves house full information', async () => {
            const houseId = 'aa231eb4-2927-46f4-a625-f6167ebc019c';

            const result = await houseManager.getHouseFullInfo(houseId);
            expect(result).toBeDefined();
            expect(result.id).toEqual(houseId);
            expect(result.location.cityName).toEqual('Brasília');
            expect(result.description).toEqual("This an automated test house for JEST.");
            expect(loggerMock.info).toHaveBeenCalled();
        }, 10000); // Timeout set to 10 seconds;
    });
});
问题根源

你混用了AWS SDK v2的aws-sdk-mock工具和AWS SDK v3的客户端,aws-sdk-mock仅支持AWS SDK v2,而你代码中使用的@aws-sdk/client-dynamodb、@aws-sdk/lib-dynamodb是v3版本,导致Mock完全未生效,实际的DynamoDB客户端被初始化,触发了凭证校验错误。

解决方案

直接用Jest Mock AWS SDK v3的API,替换掉无效的aws-sdk-mock,同时修正Logger的Mock逻辑,确保HouseManager使用Mock实例。

修复后的测试代码

import { HouseManager } from '../../lambda/house_manager';
import { Logger } from '@aws-lambda-powertools/logger';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb';

// Mock AWS SDK v3 DynamoDBClient
jest.mock('@aws-sdk/client-dynamodb', () => ({
  DynamoDBClient: jest.fn().mockImplementation(() => ({
    send: jest.fn(),
  })),
}));

// Mock DynamoDBDocumentClient及query逻辑
jest.mock('@aws-sdk/lib-dynamodb', () => ({
  DynamoDBDocumentClient: {
    from: jest.fn().mockReturnValue({
      send: jest.fn().mockResolvedValue({
        Items: [{
          PK: `HOUSE#aa231eb4-2927-46f4-a625-f6167ebc019c`,
          data: {
            id: 'aa231eb4-2927-46f4-a625-f6167ebc019c',
            name: "Jest Test House",
            description: "This an automated test house for JEST.",
            owner: "JEST-0001",
            priceDetails: {
              dailyPriceAvg: 300,
              guestFee: 50,
              petFee: 20,
              priceCalendar: "c_f5f4ec60eb80b6b4c4824eeaa569da58f99eaa103cc0b0555ade5ae7fd746a0d@group.calendar.google.com"
            },
            location: {
              active: true,
              cityId: "BSB",
              cityName: "Brasília",
              countryId: "BR",
              countryName: "Brasil",
              stateId: "DF",
              stateName: "Distrito Federal"
            },
            active: true
          },
          entity: 'HOUSE'
        }]
      }),
    }),
  },
  QueryCommand: jest.fn(),
}));

// Mock Powertools Logger
jest.mock('@aws-lambda-powertools/logger', () => ({
  Logger: jest.fn().mockImplementation(() => ({
    info: jest.fn(),
    error: jest.fn(),
  })),
}));

describe('HouseManager', () => {
  let houseManager: HouseManager;
  let mockLogger: jest.Mocked<Logger>;

  beforeEach(() => {
    jest.clearAllMocks();
    houseManager = new HouseManager();
    // 获取Mock的Logger实例
    mockLogger = new Logger() as jest.Mocked<Logger>;
  });

  describe('getHouseFullInfo', () => {
    it('should call the logger info method', () => {
      mockLogger.info('test');
      expect(mockLogger.info).toHaveBeenCalledWith('test');
    });

    it('successfully retrieves house full information', async () => {
      const houseId = 'aa231eb4-2927-46f4-a625-f6167ebc019c';

      const result = await houseManager.getHouseFullInfo(houseId);
      
      expect(result).toBeDefined();
      expect(result.id).toEqual(houseId);
      expect(result.location.cityName).toEqual('Brasília');
      expect(result.description).toEqual("This an automated test house for JEST.");
      expect(mockLogger.info).toHaveBeenCalled();
      // 验证QueryCommand是否被正确触发
      expect(QueryCommand).toHaveBeenCalled();
    }, 10000);
  });
});

关键说明

  1. AWS SDK v3采用命令式调用(如QueryCommand),而非v2的documentClient.query回调模式,Mock需对应v3的API结构。
  2. 直接MockDynamoDBDocumentClient.from方法,让它返回预设了send方法的实例,send方法直接返回Mock数据的Promise。
  3. Logger的Mock通过替换整个模块实现,确保HouseManager初始化时使用的是Mock实例,无需额外手动关联。

内容的提问来源于stack exchange,提问作者antonio Francisco de Arajo Net

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:54:50