渐进式编程课
鸿蒙 目录
第 45 课2026.09.03

让清理成功、失败两个用例不依赖执行顺序或上一个用例的资源状态。

第 45 课:清理测试的独立夹具

  • 日期:2026-09-03
  • 课程序号:第 45 课
  • 知识点:beforeEach 重建资源与关闭尝试记录

用途

让清理成功、失败两个用例不依赖执行顺序或上一个用例的资源状态。

核心概念

  • 每个用例都需要全新的可变夹具,不能把上次已关闭的实例继续用于失败测试。
  • closeAttempts 记录调用事实,opened 仅在关闭成功后改变;测试记录不代替业务状态。
  • 故意失败的关闭在 it 内被断言,不在 afterEach 中吞错。这里的 Fake 不持有真实外部资源。

最小代码或操作示例

ts
import { beforeEach, describe, expect, it } from "@ohos/hypium";

class TestChannel {
  opened: boolean = true;
  closeAttempts: number = 0;
  async close(fail: boolean): Promise<void> {
    this.closeAttempts += 1;
    await Promise.resolve();
    if (fail) { throw new Error("close failed"); }
    this.opened = false;
  }
}
export default function isolatedCleanupTest(): void {
  describe("isolated cleanup", () => {
    let channel: TestChannel = new TestChannel();
    beforeEach(() => { channel = new TestChannel(); });
    it("successfulCloseChangesState", 0, async () => {
      await channel.close(false);
      expect(channel.opened).assertFalse();
      expect(channel.closeAttempts).assertEqual(1);
    });
    it("failedClosePreservesState", 0, async () => {
      let message: string = "";
      try { await channel.close(true); }
      catch (error) { message = (error as Error).message; }
      expect(message).assertEqual("close failed");
      expect(channel.opened).assertTrue();
      expect(channel.closeAttempts).assertEqual(1);
    });
  });
}

3~5 分钟练习

把示例注册到已有 Hypium 测试入口;在每个 it 的开头增加初始状态断言,再交换两段 it 的注册顺序运行。

参考答案

ts
// 两个 it 的开头都添加:
expect(channel.opened).assertTrue();
expect(channel.closeAttempts).assertEqual(0);
// 两种注册顺序都应满足相同契约,因为 beforeEach 每次重建实例。

与上一课的联系

上一课验证清理失败传播;本课复用第 41 课的夹具隔离方法,专门证明成功与失败关闭不会共享历史状态。