第 22 课2026.08.03
适用场景:一组测试需要重复创建服务对象,或每个用例结束后都要恢复测试环境
第 22 课:Hypium 测试生命周期钩子
- 日期:2026-08-03
- 课程序号:第 22 课
- 知识点:
beforeEach、afterEach、测试前置准备与清理 - 适用场景:一组测试需要重复创建服务对象,或每个用例结束后都要恢复测试环境
承接上一课的异常路径测试:上一课分别创建服务并验证 Promise 成功、失败行为;本课把重复的测试准备和清理集中到生命周期钩子中,让每个用例只描述自身要验证的行为。
核心概念
Hypium 会围绕每个 it 执行对应钩子:
text
beforeEach -> it 测试用例 -> afterEach
beforeEach -> 下一个 it -> afterEachbeforeEach:每个测试开始前执行,适合创建全新的服务对象,避免用例之间共享可变状态。afterEach:每个测试结束后执行,适合释放监听、定时器或其他测试资源。
钩子负责准备环境,不应代替断言;真正的行为验证仍写在 it 中。
最小 ArkTS 示例
ts
import { afterEach, beforeEach, describe, expect, it } from '@ohos/hypium';
interface MessageService {
queryMessages(): Promise<string[]>;
}
class LocalMessageService implements MessageService {
queryMessages(): Promise<string[]> {
return Promise.resolve(['系统通知', '学习提醒']);
}
}
export default function messageServiceLifecycleTest(): void {
describe('MessageService lifecycle', () => {
let service: MessageService;
beforeEach(() => {
service = new LocalMessageService();
});
afterEach(() => {
// 若测试创建了监听或定时器,应在这里释放。
});
it('returnsTwoMessages', 0, async () => {
const messages: string[] = await service.queryMessages();
expect(messages.length).assertEqual(2);
});
it('returnsSystemMessageFirst', 0, async () => {
const messages: string[] = await service.queryMessages();
expect(messages[0]).assertEqual('系统通知');
});
});
}两个用例都使用 beforeEach 创建的全新实例。这样即使服务以后增加内部状态,一个用例的执行结果也不会污染另一个用例。
3~5 分钟练习
在示例中增加一个 createdCount 计数器:
- 在
beforeEach中创建服务后将其加1。 - 新增一个测试,断言当前至少执行过一次创建。
- 思考为什么服务对象仍应每次重新创建,而不是只在
describe中创建一次。
参考答案
ts
let service: MessageService;
let createdCount: number = 0;
beforeEach(() => {
service = new LocalMessageService();
createdCount += 1;
});
it('createsServiceBeforeTest', 0, () => {
expect(createdCount > 0).assertTrue();
});每次重新创建服务能隔离可变状态,使测试结果不依赖用例执行顺序。实际项目中,比起断言钩子本身,更重要的是用钩子准备环境、在 it 中断言业务行为。
与上一课的联系
上一课用可控失败实现验证异常路径,测试中需要自行准备服务对象;本课用 beforeEach 统一创建每个用例所需的独立对象,并用 afterEach 预留成对清理资源的位置。下一步可以学习 beforeAll / afterAll 与每用例钩子的差异,理解何时可以安全共享昂贵但只读的测试资源。