close

作用域清理

Rstest 支持对测试中的临时变更进行作用域清理。当运行时或工具链支持 explicit resource management 时,你可以使用 using 在代码块退出时自动恢复资源。

这适用于测试中临时修改共享状态的场景,例如 spy、环境变量、全局变量或 fake timers。

Disposable / using 语法

rs.stubEnv()rs.stubGlobal()rs.useFakeTimers() 会返回可释放资源,可配合 using 使用。

Spy 清理

Mock 和 spy 实现了 Symbol.dispose,因此通过 rs.spyOn() 创建的 spy 会在 using 代码块退出时自动恢复。

logger.test.ts
import { expect, rs, test } from '@rstest/core';

test('logs a warning', () => {
  {
    using warn = rs.spyOn(console, 'warn').mockImplementation(() => undefined);

    console.warn('invalid payload');
    expect(warn).toHaveBeenCalledWith('invalid payload');
  }

  // console.warn 在这里已恢复
});

更多 spy 示例可以参考 Mock

环境变量

rs.stubEnv() 会返回一个可释放资源。当它离开 using 作用域时,只会恢复当前作用域内的 env stub。

env.test.ts
import { expect, rs, test } from '@rstest/core';

test('uses test env', () => {
  {
    using _env = rs.stubEnv('NODE_ENV', 'test');

    expect(process.env.NODE_ENV).toBe('test');
  }

  // NODE_ENV 在这里已恢复
});

嵌套的 env stub 会按相反顺序恢复:

using _outer = rs.stubEnv('FEATURE_FLAG', 'on');
expect(process.env.FEATURE_FLAG).toBe('on');

{
  using _inner = rs.stubEnv('FEATURE_FLAG', 'off');
  expect(process.env.FEATURE_FLAG).toBe('off');
}

expect(process.env.FEATURE_FLAG).toBe('on');

你仍然可以调用 rs.unstubAllEnvs() 来恢复当前测试中的所有 env stub。

全局变量

rs.stubGlobal() 同样会返回一个可释放资源,适合临时替换全局 API。

global.test.ts
import { expect, rs, test } from '@rstest/core';

test('uses a global feature flag', () => {
  {
    using _global = rs.stubGlobal('__FEATURE_ENABLED__', true);

    expect(globalThis.__FEATURE_ENABLED__).toBe(true);
  }

  // __FEATURE_ENABLED__ 在这里已恢复
});

你仍然可以调用 rs.unstubAllGlobals() 来恢复当前测试中的所有 global stub。

Fake timers

rs.useFakeTimers() 会返回一个可释放资源,在代码块退出时恢复真实定时器。

timer.test.ts
import { expect, rs, test } from '@rstest/core';

test('runs delayed work', () => {
  {
    using _timers = rs.useFakeTimers();

    const fn = rs.fn();
    setTimeout(fn, 1000);

    rs.advanceTimersByTime(1000);
    expect(fn).toHaveBeenCalledTimes(1);
  }

  expect(rs.isFakeTimers()).toBe(false);
});

异步资源

对于实现了 Symbol.asyncDispose 的异步资源,可以使用 await using。Rstest 的 browser provider 资源已在内部支持异步释放,因此 provider page、context 和 browser 可以通过相同的 explicit resource management 协议关闭。

await using resource = createAsyncResource();

await resource.run();
// 这里会等待 resource[Symbol.asyncDispose]() 执行完成

同步清理使用 using,需要等待异步清理完成时使用 await using