第 21 课2026.07.31
适用场景:数据服务可能请求失败,需要确认失败会按接口语义向调用方抛出,而不是被服务或 UI 静默吞掉
第 21 课:Hypium 异常路径测试
- 日期:2026-07-31
- 课程序号:第 21 课
- 知识点:可控失败实现、Promise 拒绝、异步异常断言
- 适用场景:数据服务可能请求失败,需要确认失败会按接口语义向调用方抛出,而不是被服务或 UI 静默吞掉
承接上一课的数据服务单元测试:上一课验证成功结果和空结果;本课补上失败路径,确认服务拒绝 Promise 时,调用方能够感知异常。
核心概念
异常路径测试需要一个结果可控的失败实现:
text
FailingMessageService
-> queryMessages()
-> Promise.reject(...)
-> 测试捕获异常并断言确实发生测试重点是可观察的服务契约,而不是页面提示文案。失败服务只用于测试,能够稳定复现错误,避免依赖真实网络是否刚好断开。
最小 ArkTS 示例
ts
import { describe, expect, it } from '@ohos/hypium';
interface MessageService {
queryMessages(): Promise<string[]>;
}
class FailingMessageService implements MessageService {
queryMessages(): Promise<string[]> {
return Promise.reject(new Error('network unavailable'));
}
}
export default function messageServiceFailureTest(): void {
describe('MessageService failure', () => {
it('rejectsWhenQueryFails', 0, async () => {
const service: MessageService = new FailingMessageService();
let rejected: boolean = false;
try {
await service.queryMessages();
} catch (error) {
rejected = true;
}
expect(rejected).assertTrue();
});
});
}await 遇到被拒绝的 Promise 会进入 catch。若服务意外吞掉错误并返回空数组,rejected 会保持 false,测试就会失败,从而暴露服务契约已经改变。
3~5 分钟练习
新增一个 SuccessfulMessageService,让它返回 ['系统通知'];复用相同的 try/catch 结构,断言调用成功时 rejected 为 false。
参考答案
ts
class SuccessfulMessageService implements MessageService {
queryMessages(): Promise<string[]> {
return Promise.resolve(['系统通知']);
}
}
it('doesNotRejectWhenQuerySucceeds', 0, async () => {
const service: MessageService = new SuccessfulMessageService();
let rejected: boolean = false;
try {
await service.queryMessages();
} catch (error) {
rejected = true;
}
expect(rejected).assertFalse();
});与上一课的联系
上一课验证 MessageService 在成功和空数据场景下遵守返回契约;本课验证失败会通过 Promise 拒绝继续向上传递。至此,数据服务的主要成功与失败分支都有了可重复执行的证据,下一步可以学习使用测试生命周期钩子减少重复的测试准备代码。