使用Jest模拟Azure SDK的PagedAsyncIterableIterator时byPage调用失败排查
Jest模拟Azure SDK的PagedAsyncIterableIterator时.byPage()调用失败问题
我在使用Jest模拟Azure SDK的PagedAsyncIterableIterator时,单元测试调用.byPage()方法失败,报错TypeError: this.storageManagementClient.localUsersOperations.list(...).byPage is not a function。list方法的模拟能正常运行,但调用list()后的.byPage()子方法失效。
业务代码
async findAll(accountId: number): Promise<Array<SftpUserResponseDto>> { // ... // Get a list of Users from the Azure SFTP Blob Account const localUserPages = this.storageManagementClient.localUsersOperations .list(this.resourceGroup, this.storageAccount) .byPage(); for await (const page of localUserPages) { // Do stuff with the list of Users on the page } // ... }
单元测试代码
describe('SftpUsersService', () => { let mockStorageManagementClient: Partial<StorageManagementClient>; beforeEach(async () => { mockStorageManagementClient = { localUsersOperations: { delete: jest.fn(), list: jest.fn().mockResolvedValue(sftpUsersMocks.listPage), createOrUpdate: jest.fn().mockResolvedValue(sftpUsersMocks.localUser1), get: jest.fn().mockResolvedValue(sftpUsersMocks.localUser1), listKeys: jest.fn(), regeneratePassword: jest.fn(), }, }; const module: TestingModule = await Test.createTestingModule({ providers: [ // ... { provide: StorageManagementClient, useValue: mockStorageManagementClient, }, ], }).compile(); }; // ... }); describe('findAll', () => { it('should return a list of users', async () => { const accountId = sftpUsersMocks.account1.accountId; const users = await service.findAll(accountId); expect(users).toEqual(sftpUsersMocks.listResponse); expect( mockStorageManagementClient.localUsersOperations.list, ).toHaveBeenCalledWith(accountId); }); }); });
模拟对象代码
export class SftpUsersMocks { listPage: PagedAsyncIterableIterator<LocalUser, LocalUser[], PageSettings> = { byPage: jest.fun(), [Symbol.asyncIterator]: jest.fn(), next: jest.fn(), }; };
尝试过的替代方案
我还试过直接在list的mock里返回带byPage的对象,但依然无效:
mockStorageManagementClient = { localUsersOperations: { delete: jest.fn(), list: jest.fn().mockResolvedValue({ byPage: jest.fn(), }), }, };
问题原因与解决方法
核心问题
Azure SDK的list方法不返回Promise,而是直接返回PagedAsyncIterableIterator对象。你当前用mockResolvedValue把它模拟成了Promise,导致业务代码里调用.list(...).byPage()时,实际是在Promise实例上调用方法,自然找不到byPage。
修复步骤
- 替换mock方法:把
mockResolvedValue改成mockReturnValue,直接返回模拟的迭代器对象:
// 在beforeEach的localUsersOperations里修改list的mock list: jest.fn().mockReturnValue(sftpUsersMocks.listPage),
- 修正模拟对象的笔误:
jest.fun()是拼写错误,要改成jest.fn(),同时给byPage和异步迭代器返回可遍历的异步生成器,确保for await...of能正常运行:
export class SftpUsersMocks { listPage: PagedAsyncIterableIterator<LocalUser, LocalUser[], PageSettings> = { byPage: jest.fn().mockReturnValue(async function* () { // 模拟分页数据,这里返回你需要的测试数据 yield sftpUsersMocks.listResponse; }()), [Symbol.asyncIterator]: jest.fn().mockReturnValue(async function* () { yield sftpUsersMocks.listResponse; }()), next: jest.fn(), }; };
修改后,业务代码调用list(...).byPage()时,拿到的就是带正确方法的模拟迭代器,单元测试即可正常执行。
内容的提问来源于stack exchange,提问作者S.S.
相关产品推荐
相关产品推荐

