第 28 课2026.08.11
适用场景:保存、提交或支付失败时,后续成功通知、跳转等操作必须停止
第 28 课:Hypium 异步失败交互验证
- 日期:2026-08-11
- 课程序号:第 28 课
- 知识点:验证前置异步操作失败后,不会继续触发成功通知
- 适用场景:保存、提交或支付失败时,后续成功通知、跳转等操作必须停止
承接上一课:上一课验证“保存完成 → 发送通知”的成功顺序;本课补齐失败路径,验证保存被拒绝时通知不会发生。
核心概念
await遇到被拒绝的 Promise 会立即抛出异常,当前方法中它后面的语句不会继续执行。- 失败测试替身应主动返回
Promise.reject(),稳定制造可重复的异常路径。 - 失败用例只断言业务契约:错误向上传递,且成功通知没有发生;不要在 UI 层伪造成功状态。
最小 ArkTS / Hypium 示例
ts
import { describe, expect, it } from '@ohos/hypium';
interface DraftService {
save(content: string): Promise<void>;
}
interface NoticeService {
send(message: string): void;
}
class DraftPublisher {
constructor(
private draftService: DraftService,
private noticeService: NoticeService
) {}
async publish(content: string): Promise<void> {
await this.draftService.save(content);
this.noticeService.send('发布成功');
}
}
class FailingDraftService implements DraftService {
save(content: string): Promise<void> {
return Promise.reject(new Error(`保存失败:${content}`));
}
}
class SpyNoticeService implements NoticeService {
callCount: number = 0;
send(message: string): void {
this.callCount += 1;
}
}
export default function draftPublisherFailureTest(): void {
describe('DraftPublisher failure', () => {
it('doesNotNotifyWhenSaveFails', 0, async () => {
const noticeService: SpyNoticeService = new SpyNoticeService();
const publisher: DraftPublisher = new DraftPublisher(
new FailingDraftService(),
noticeService
);
let errorMessage: string = '';
try {
await publisher.publish('鸿蒙笔记');
} catch (error) {
errorMessage = (error as Error).message;
}
expect(errorMessage).assertEqual('保存失败:鸿蒙笔记');
expect(noticeService.callCount).assertEqual(0);
});
});
}FailingDraftService 让保存稳定失败。异常从 publish() 向上传递,同时 send() 位于 await save() 之后,因此调用次数保持为 0。
3~5 分钟练习
临时把 this.noticeService.send('发布成功') 移到 await this.draftService.save(content) 前面,运行测试并观察哪条断言失败;随后恢复正确顺序。
参考答案
通知提前后,即使保存失败,callCount 也已经变为 1,所以“不发送成功通知”的断言失败。正确实现必须先等待保存成功:
ts
async publish(content: string): Promise<void> {
await this.draftService.save(content);
this.noticeService.send('发布成功');
}与上一课的联系
上一课验证成功路径中的先后顺序,本课用同一条调用链验证失败会截断后续交互。合在一起,测试同时覆盖“成功后通知”和“失败不通知”两条关键契约。