鸿蒙 预览数据模拟:Hamock

一、Hamock

在预览场景中,由于代码的运行环境与真机设备上的运行环境不同,调用部分接口时无法获取到有效的返回值。

这样就无法在预览时查看到不同返回值带来的界面变化。

方案 :Hamock 提供了预览场景的模拟功能,在不改变业务运行逻辑的同时,可以:

  • 模拟 UI 组件上的属性或方法

  • 或模拟 import 的模块接口

适用范围

仅 API 11 及以上版本的 Stage 模型工程支持。

二、使用前提

使用 Hamock 在预览场景模拟,需要在工程或模块的 oh-package.json5 中添加该依赖,然后重新同步工程。

复制代码
"devDependencies": {
  "ohos/hamock": "1.0.0"
}

三、UI 组件上的 Mock

Hamock 提供了 @MockSetup 用于修饰 Mock 方法,仅支持声明式范式的组件。

工作机制

  • 当预览该组件时,预览运行时将在组件初始化时执行被 @MockSetup 修饰的方法

  • 可以在这个被修饰的方法内重定义组件的方法 或重赋值组件的属性,其将在预览时生效

说明: @MockSetup 修饰的方法仅在预览场景会自动触发,并先于组件的 aboutToAppear 执行。

场景一:Mock UI 组件的方法

第一步:引入 Hamock

复制代码
import { MockKit, when, MockSetup } from '@ohos/hamock';

第二步:定义并修饰方法

在目标组件中定义一个方法,并用 @MockSetup 修饰该方法。在这个方法中,使用 MockKit 模拟目标方法。

复制代码
import { MockKit, when, MockSetup } from '@ohos/hamock';

@Entry
@Component
struct Index {
  //...
  @MockSetup
  randomName() {
    let mocker: MockKit = new MockKit();
    let mockfunc: Object = mocker.mockFunc(this, this.method1);
    // mock指定的方法在指定入参的返回值
    when(mockfunc)('test').afterReturn(1);
  }

  //业务场景调用方法
  const result = this.method1('test'); // in previewer, result = 1
}

场景二:Mock UI 组件的属性

第一步:引入 Hamock

复制代码
import { MockSetup } from '@ohos/hamock';

第二步:定义并修饰方法

在目标组件中定义一个方法,并用 @MockSetup 修饰该方法。在这个方法中,对于需要 Mock 的属性,可以重新赋值。

属性 Mock 的限制

ArkUI 部分类型属性不支持 Mock ,如 readonly、@ObjectLink。

被 @Link / @Consume / @Prop / @BuilderParam 装饰器修饰的变量,ArkUI 语法要求父容器需要有对应属性的定义。因此更推荐开发者通过定义一个预览场景父容器(并通过父容器传递合适的数据)来预览这一类的组件。

四、模块的 Mock

模块的 Mock 支持对系统模块、依赖模块及本地模块的 Mock。

工作机制

  1. 通过新建 ArkTS 文件定义 Mock 实现代码

  2. 在 mock-config.json5 配置文件中定义目标模块与 Mock 实现代码文件的映射关系

  3. 目标模块与 Mock 实现代码文件为一对一的关系 ,即对于同一目标模块,仅支持一份 Mock 实现代码

  4. 预览运行时,所有页面 import 目标模块都将指向这一份 Mock 实现代码

场景一:系统模块 / 依赖的模块

第一步:新建 Mock 文件

在 src/mock 目录下新建一个 ArkTS 文件,在这个文件内定义目标模块的 Mock 实现。

复制代码
// src/mock/MeasureText.mock.ets
import MeasureText from '@ohos.measure'

// 类的mock使用继承(extends)的方式实现
class MockMeasureText extends MeasureText {
  // 定义mock实现
  static measureText(): number {
    console.log('Return value of the mock measureText function')
    return 100;
  }
};

export default MockMeasureText;

说明:

用户在对类定义 Mock 的实现时,建议使用继承(extends)的方式实现 。若不使用继承,需要保证代码中使用到依赖模块的所有方法都重新定义 Mock 实现。

第二步:配置映射关系

在 Mock 配置文件 src/mock/mock-config.json5 中定义目标模块与 Mock 实现的替换关系。该替换关系会在预览场景下生效。

复制代码
{
  "@ohos.measure": { // 待替换的moduleName
    "source": "src/mock/MeasureText.mock.ets" // Mock代码的路径,相对于模块根目录
  },
}

第三步:验证 Mock 是否生效

在原调用处中添加 Hilog 日志,方便在预览时,在 Log 中打印获取返回值,从而验证 Mock 是否生效。

复制代码
hilog.debug(DomainNumber, logTag, 'Mock %{public}s', `${MeasureText.measureText({textContent: 'Hello World'})}`);

场景二:本地模块

第一步:新建 Mock 文件

在 src/mock 目录下新建一个 ArkTS 文件,在这个文件内定义目标模块的 Mock 实现。

复制代码
// src/mock/module/utils/CommonUtils.mock.ets
// 导入本地模块
import LibDefaultExport from '../../../main/ets/utils/CommonUtils'; // get origin default export
import { methodA, ObjectB } from '../../../main/ets/utils/CommonUtils'; // get origin export on demand

class DefaultExportMock extends LibDefaultExport {
  // 定义mock实现
  public static getName(): String {
    return "Mocked Name";
  }
};

// Mock methodA方法
export const methodAMock = (): string => {
  return "methodA Mocked"
}
export {
  methodAMock as methodA,
  ObjectB,
}

export default DefaultExportMock;

原始文件 CommonUtils.ets 示例:

复制代码
export default class CommonUtils {
  public static getName(): String {
    return "origin name";
  }

  public static getTitle(): String {
    return "origin title";
  }
}

export const methodA = (): string => {
  return "methodA"
}

export const ObjectB: Object = new Object();

说明 :本地模块的 Mock 仅支持 src/main/ets 目录下的 ArkTS 或 TS 文件。

第二步:配置映射关系

在 Mock 配置文件 src/mock/mock-config.json5 中定义目标模块与 Mock 实现的替换关系。该替换关系会在预览场景下生效。

复制代码
{
  "utils/CommonUtils.ets": { // 本地模块只支持ets/xxx的相对路径,并需明确文件后缀
    "source": "src/mock/module/utils/CommonUtils.mock.ets"
  },
}

第三步:验证 Mock 是否生效

在原调用处中添加 Hilog 日志,方便在预览时,在 Log 中打印获取返回值,从而验证 Mock 是否生效。

复制代码
hilog.debug(DomainNumber, logTag, 'Mock %{public}s', CommonUtils.getName());

五、使用方式对比

对比项 UI 组件方法 Mock UI 组件属性 Mock 模块 Mock
装饰器 @MockSetup @MockSetup 无(配置文件驱动)
引入方式 import { MockKit, when, MockSetup } import { MockSetup } import ... from 目标模块
实现方式 MockKit.mockFunc + when(...).afterReturn(...) 直接重新赋值属性 继承 extends + 重写方法
配置文件 无 无 src/mock/mock-config.json5
映射关系 无 无 目标模块 ↔ Mock 文件,一对一
触发时机 预览时组件初始化,先于 aboutToAppear 同左 预览运行时,所有 import 指向 Mock
支持范围 声明式范式组件 声明式范式组件 系统模块、依赖模块、本地模块
相关推荐
贾伟康4 小时前
【化学实验室|04】HarmonyOS ArkTS 场景选择器实战:让 13 个离线实验的入口、筛选和返回路径保持一致
harmonyos·arkts·canvas·arkui·化学实验
特立独行的猫a4 小时前
仓颉语言GUI开发实战:用仓颉写串口/网络二合一调试助手
网络·ui·gui·harmonyos·tauri·仓颉
hqzing13 小时前
把 glibc 移植到鸿蒙 PC 上:它能用来做什么
华为·harmonyos
OH_TPC19 小时前
HarmonyOS APP开发---“习惯猫“习惯打卡App,需要用到这个库
华为·harmonyos·鸿蒙
熊猫钓鱼>_>21 小时前
开源鸿蒙平台 KMP 三方库 kotlin-csv 适配全流程:从编码假设到沙箱真机互通验证
开发语言·人工智能·华为·kotlin·harmonyos·鸿蒙
马剑威(威哥爱编程)1 天前
【共创稿事节】HarmonyOS 7 Agent 开发实战 09:Agent 测试评测集
华为·harmonyos
威哥爱编程1 天前
HarmonyOS 7 Agent 开发实战 04:云端 RAG 搭企业私有知识库问答
agent·harmonyos
威哥爱编程1 天前
HarmonyOS 7 Agent 开发实战 05:流式输出做打字机对话
agent·harmonyos
donk13141 天前
React Native for OpenHarmony 实战:三方库 react-native-circular-action-menu 的鸿蒙化适配指南
javascript·分布式·react native·react.js·wpf·harmonyos