Jest测试中如何等待Memory类的异步内存测量Promise执行完成?
解决Jest测试中等待异步内存测量完成的问题
我使用了Performance.measureUserAgentSpecificMemory API编写了简化的Memory类,代码如下:
export class Memory { private stopped = false private isUserAgentSpecificMemorySupported = true public memoryData: any = [] constructor() {} public startMonitoring(): () => void { if (this.isUserAgentSpecificMemorySupported) { this.scheduleMeasurement() } return () => { this.stopped = true } } private async performMeasurement(): Promise<void> { const memory = await (window.performance as any).measureUserAgentSpecificMemory() const type = memory.breakdown.filter((e: any) => e.types.includes('JavaScript')) this.memoryData.push(type[0].bytes) } // 补充缺失的scheduleMeasurement方法(原代码中调用但未实现) private scheduleMeasurement(): void { this.performMeasurement().catch(err => console.error('内存测量失败:', err)) } }
对应的Jest测试文件如下,但不清楚如何让测试等待异步操作完成后再执行断言:
import {Memory} from './memory' type UserAgentSpecificMemoryBreakdown = { bytes: number types: Array<string> } type UserAgentSpecificMemory = { bytes: number breakdown: Array<UserAgentSpecificMemoryBreakdown> } type MockWindow = { crossOriginIsolated?: boolean performance: { measureUserAgentSpecificMemory?: () => Promise<UserAgentSpecificMemory> } } const data = { bytes: 1500, breakdown: [ { bytes: 1000000, types: ['JavaScript'], }, { bytes: 0, types: ['DOM'], }, ], } describe('Test Memory Class', () => { let mockWindow: MockWindow let windowSpy: jest.SpyInstance beforeEach(() => { windowSpy = jest.spyOn(window, 'window', 'get') mockWindow = { ...window, performance: { measureUserAgentSpecificMemory: jest.fn(() => Promise.resolve(data)), }, } windowSpy.mockImplementation(() => mockWindow) }) afterEach(() => { windowSpy.mockRestore() }) it('should measure User Agent Specific Memory', async () => { let memory = new Memory() memory.startMonitoring() expect(memory.memoryData).toEqual([1000000]) }) })
可行的解决方法
方法1:等待Mock函数的Promise完成
直接等待我们mock的measureUserAgentSpecificMemory函数返回的Promise完成,确保异步测量执行完毕后再断言:
it('should measure User Agent Specific Memory', async () => { let memory = new Memory() // 拿到mock的测量函数 const mockMeasureFn = mockWindow.performance.measureUserAgentSpecificMemory as jest.Mock memory.startMonitoring() // 等待异步测量完成 await mockMeasureFn() expect(memory.memoryData).toEqual([1000000]) })
方法2:使用flushPromises等待所有Pending Promise
如果项目中引入了@testing-library/react,可以直接用它提供的flushPromises函数,等待所有待处理的Promise完成:
import { flushPromises } from '@testing-library/react'; it('should measure User Agent Specific Memory', async () => { let memory = new Memory() memory.startMonitoring() await flushPromises() expect(memory.memoryData).toEqual([1000000]) })
如果没有依赖这个库,也可以自己实现一个简单的flushPromises:
function flushPromises(): Promise<void> { return new Promise(resolve => setImmediate(resolve)) }
方法3:修改Memory类暴露异步操作(可选)
如果允许调整原类的逻辑,可以让startMonitoring或者performMeasurement暴露Promise,方便测试等待:
// 修改Memory类的startMonitoring方法 public async startMonitoring(): () => void { if (this.isUserAgentSpecificMemorySupported) { await this.performMeasurement() } return () => { this.stopped = true } }
然后测试中直接await:
it('should measure User Agent Specific Memory', async () => { let memory = new Memory() await memory.startMonitoring() expect(memory.memoryData).toEqual([1000000]) })
注意:这种方法会改变原方法的同步返回特性,需要根据业务场景权衡是否适用。
内容的提问来源于stack exchange,提问作者user1503606
相关产品推荐
相关产品推荐

