单元测试Stub dynamodb-onetable遇OneTableArgError报错求助
解决Stub dynamodb-onetable时的OneTableArgError问题
问题根源
你Stub DataService.getData 的写法本身没问题,但DataService模块在被导入时就会执行顶部的Table实例化代码——测试环境下如果没有正确配置TableName变量,模块加载阶段就会触发「Missing Name Property」错误,和你是否Stub getData完全无关。
解决方案
方案一:重构为依赖注入(推荐,更易维护测试)
修改代码结构,将Table实例作为依赖传入DataService,避免模块加载时直接实例化Table:
- 修改DataService.ts
import { Table } from 'dynamodb-onetable'; export default class DataService { #empDetailModel; constructor(tableInstance: Table) { this.#empDetailModel = tableInstance.getModel('empDetail'); } async getData(empId: string, type: string) { const params = { empId, type }; // 注意原代码中params写的是projectId,这里修正为empId const response = await this.#empDetailModel.find(params); logger.trace('response', { response }); return response; } }
- 修改lambda.ts
在lambda层创建DataService实例并导出:
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import Dynamo from 'dynamodb-onetable/Dynamo'; import { Table } from 'dynamodb-onetable'; import DataService from './path/to/DataService'; export const client = new Dynamo({ client: new DynamoDBClient({ region: REGION }), }); const workspaceTable = new Table({ client, name: TableName, schema, logger: true, partial: false, }); export const dataService = new DataService(workspaceTable);
- 修改getDetails.ts
使用导出的DataService实例:
import { dataService } from '../lambda'; const dataDetails = await dataService.getData( empId, 'EMPLOYEE-SAVEDATA' );
- 测试代码编写
测试时可以完全控制DataService的依赖,无需担心模块加载时的Table实例化错误:
import sinon from 'sinon'; import DataService from '../path/to/DataService'; import getDetails from '../path/to/getDetails'; describe('getDetails', () => { it('should return mock employee data', async () => { // 创建模拟的DataService实例 const mockDataService = new DataService({} as any); // Stub getData方法返回预设数据 const getDataStub = sinon.stub(mockDataService, 'getData').resolves({ id: 'test-emp-123', name: 'Test Employee', type: 'EMPLOYEE-SAVEDATA' }); // 此处需要替换getDetails中的dataService依赖为mock实例,可通过依赖注入或模块mock实现 const result = await getDetails('test-emp-123', 'EMPLOYEE-SAVEDATA'); sinon.assert.calledOnceWithExactly(getDataStub, 'test-emp-123', 'EMPLOYEE-SAVEDATA'); expect(result).toEqual({ id: 'test-emp-123', name: 'Test Employee', type: 'EMPLOYEE-SAVEDATA' }); }); });
方案二:快速修复(不修改原有结构)
如果不想重构代码,可在测试文件最顶部提前mock Table类或设置环境变量:
- Mock Table类
import sinon from 'sinon'; import { Table } from 'dynamodb-onetable'; // 必须在导入DataService之前mock Table,避免模块加载时实例化真实Table sinon.stub(Table.prototype, 'getModel').returns({ find: sinon.stub().resolves({ /* 预设模拟数据 */ }) }); // 现在再导入相关依赖 import DataService from '../path/to/DataService'; import getDetails from '../path/to/getDetails'; describe('getDetails', () => { it('should return mock data', async () => { const getDataStub = sinon.stub(DataService, 'getData').resolves({ id: 'test-emp-456', name: 'Mock Employee' }); const result = await getDetails('test-emp-456', 'EMPLOYEE-SAVEDATA'); sinon.assert.calledOnce(getDataStub); expect(result).toEqual({ id: 'test-emp-456', name: 'Mock Employee' }); }); });
- 设置环境变量(辅助)
如果是因为TableName未定义导致的错误,可在测试前赋值:
// 测试文件最顶部 process.env.TableName = 'mock-test-table';
内容的提问来源于stack exchange,提问作者Tejaswini
相关产品推荐
相关产品推荐

