渐进式编程课
鸿蒙 目录
第 20 课2026.07.30

适用场景:数据服务已经从页面中拆出,需要在不启动 UI 的情况下验证服务契约

第 20 课:Hypium 数据服务单元测试

  • 日期:2026-07-30
  • 课程序号:第 20 课
  • 知识点:Hypium、describe / it / expect、异步服务测试
  • 适用场景:数据服务已经从页面中拆出,需要在不启动 UI 的情况下验证服务契约

承接上一课的接口抽象:上一课让不同服务实现遵守同一个 MessageService 接口;本课用单元测试确认实现确实返回契约约定的数据。

核心概念

Hypium 测试通常由三部分组成:

text
describe:组织一组相关测试
it:描述一个具体行为
expect:断言实际结果符合预期

异步服务返回 Promise,所以测试函数使用 async,并通过 await 等待真实结果后再断言。测试直接调用数据服务,不经过页面,也不为 UI 伪造状态。

最小 ArkTS 示例

ts
import { describe, expect, it } from '@ohos/hypium';

interface MessageService {
  queryMessages(): Promise<string[]>;
}

class LocalMessageService implements MessageService {
  queryMessages(): Promise<string[]> {
    return Promise.resolve(['系统通知', '学习提醒']);
  }
}

export default function messageServiceTest(): void {
  describe('MessageService', () => {
    it('returnsLocalMessages', 0, async () => {
      const service: MessageService = new LocalMessageService();

      const messages: string[] = await service.queryMessages();

      expect(messages.length).assertEqual(2);
      expect(messages[0]).assertEqual('系统通知');
    });
  });
}

这里验证的是接口的可观察结果:数组长度和第一条消息。若实现改成网络请求,只要仍遵守相同契约,页面无需改变,测试也可以继续验证返回行为。

3~5 分钟练习

新增 EmptyMessageService,让 queryMessages() 返回空数组;再添加一个测试用例,断言返回数组长度为 0。

参考答案

ts
class EmptyMessageService implements MessageService {
  queryMessages(): Promise<string[]> {
    return Promise.resolve([]);
  }
}

it('returnsEmptyMessages', 0, async () => {
  const service: MessageService = new EmptyMessageService();
  const messages: string[] = await service.queryMessages();

  expect(messages.length).assertEqual(0);
});

与上一课的联系

上一课用 MessageService 接口建立了可替换的数据服务契约;本课不经过 ArkUI 页面,直接验证两个实现的返回结果。这样服务行为出错时,可以先在数据层复现和定位,而不是在 UI 层增加兜底。