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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:01:08