渐进式编程课
鸿蒙 目录
第 27 课2026.08.10

适用场景:业务要求前一个异步操作成功完成后,才能执行通知、跳转或后续提交

第 27 课:Hypium 异步交互顺序验证

  • 日期:2026-08-10
  • 课程序号:第 27 课
  • 知识点:用共享事件记录验证多个异步依赖的调用顺序
  • 适用场景:业务要求前一个异步操作成功完成后,才能执行通知、跳转或后续提交

承接上一课:上一课用 Spy 验证单个依赖的调用次数和参数;本课让多个 Spy 写入同一事件记录,验证它们之间的重要先后顺序。

核心概念

  • await 不只是等待结果,也表达业务顺序:前一个 Promise 完成后,才继续执行下一步。
  • 多个测试替身共享一个 string[] 事件记录;测试执行完后,直接断言关键事件的排列。
  • 只记录业务契约,例如“保存完成 → 发送通知”,不要把对象创建、日志打印等内部细节写进顺序断言。

最小 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 SpyDraftService implements DraftService {
  constructor(private events: string[]) {}

  save(content: string): Promise<void> {
    return Promise.resolve().then(() => {
      this.events.push(`saved:${content}`);
    });
  }
}

class SpyNoticeService implements NoticeService {
  constructor(private events: string[]) {}

  send(message: string): void {
    this.events.push(`notified:${message}`);
  }
}

export default function draftPublisherTest(): void {
  describe('DraftPublisher', () => {
    it('notifiesAfterSaveCompletes', 0, async () => {
      const events: string[] = [];
      const publisher: DraftPublisher = new DraftPublisher(
        new SpyDraftService(events),
        new SpyNoticeService(events)
      );

      await publisher.publish('鸿蒙笔记');

      expect(events.join('|')).assertEqual(
        'saved:鸿蒙笔记|notified:发布成功'
      );
    });
  });
}

SpyDraftService 在保存 Promise 完成时记录事件;只有 await save() 正确结束后,通知事件才会出现在它后面。

3~5 分钟练习

临时删除 DraftPublisher.publish() 中的 await,直接调用 this.draftService.save(content),再运行测试并观察顺序断言为什么失败;随后恢复 await。

参考答案

删除 await 后,save() 的 .then() 回调稍后执行,而 send() 会立即记录通知,实际顺序将变为:

text
notified:发布成功|saved:鸿蒙笔记

恢复正确实现:

ts
async publish(content: string): Promise<void> {
  await this.draftService.save(content);
  this.noticeService.send('发布成功');
}

与上一课的联系

上一课回答“某个依赖调用了几次、参数是什么”;本课进一步回答“多个依赖是否按业务要求依次发生”。两者都使用 Spy,但只断言对外重要的交互契约。