第 23 课2026.08.04
适用场景:一组测试需要复用创建成本较高、且测试期间保持只读的资源
第 23 课:Hypium 套件级生命周期钩子
- 日期:2026-08-04
- 课程序号:第 23 课
- 知识点:
beforeAll、afterAll与每用例钩子的区别 - 适用场景:一组测试需要复用创建成本较高、且测试期间保持只读的资源
承接上一课:beforeEach / afterEach 为每个用例提供隔离环境;本课学习只执行一次的套件级钩子,并明确共享资源的安全边界。
核心概念
Hypium 在同一个 describe 中的大致执行顺序是:
text
beforeAll
beforeEach -> it -> afterEach
beforeEach -> it -> afterEach
afterAllbeforeAll:整组测试开始前执行一次,适合读取固定配置、构造只读测试数据。afterAll:整组测试结束后执行一次,适合释放套件级资源。beforeEach:每个用例前执行,适合创建带可变状态的服务实例。
不要通过 beforeAll 共享会被测试修改的对象,否则用例可能相互污染,并依赖执行顺序。
最小 ArkTS 示例
ts
import { afterAll, beforeAll, beforeEach, describe, expect, it } from '@ohos/hypium';
class MessageService {
private readonly prefix: string;
constructor(prefix: string) {
this.prefix = prefix;
}
format(message: string): string {
return `${this.prefix}${message}`;
}
}
export default function messageServiceSuiteTest(): void {
describe('MessageService suite', () => {
let readonlyPrefix: string;
let service: MessageService;
beforeAll(() => {
readonlyPrefix = '[测试]';
});
beforeEach(() => {
service = new MessageService(readonlyPrefix);
});
afterAll(() => {
readonlyPrefix = '';
});
it('formatsFirstMessage', 0, () => {
expect(service.format('通知')).assertEqual('[测试]通知');
});
it('formatsSecondMessage', 0, () => {
expect(service.format('提醒')).assertEqual('[测试]提醒');
});
});
}固定前缀由 beforeAll 准备一次;服务实例仍在 beforeEach 中重新创建,因此将来服务增加可变状态时,各用例仍互不影响。
3~5 分钟练习
新增一个只读后缀 readonlySuffix:在 beforeAll 中设为 !,让 format() 返回 [测试]通知!,并修改第一条断言。
参考答案
ts
let readonlySuffix: string;
beforeAll(() => {
readonlyPrefix = '[测试]';
readonlySuffix = '!';
});
// 将后缀作为构造参数传入,并在 format 中拼接。
expect(service.format('通知')).assertEqual('[测试]通知!');关键是后缀在所有用例中保持只读;如果测试会修改它,就应改为在 beforeEach 中重新准备。
与上一课的联系
上一课用 beforeEach / afterEach 隔离每个测试用例;本课补充 beforeAll / afterAll,用于整组测试共享只读资源。两者结合后,可以同时兼顾资源准备成本与用例隔离。