You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest模拟React Native的Platform.OS及测试静态常量?

React Native Jest测试平台相关静态常量的优化方案

针对你遇到的静态常量在导入阶段就被固化、导致测试无法动态切换平台的问题,除了jest.resetModules()+require的方式,还有以下几种更简便的实现方案:

1. 直接Mock依赖的静态常量

既然items模块依赖的是@my/utils导出的isIOS常量,我们可以直接Mock这个常量的值,跳过对Platform的修改,更直接高效:

// 测试文件
it("should be android", () => {
  // 临时Mock utils模块的isIOS为false
  jest.mock("@my/utils", () => ({ isIOS: false }));
  // 重新导入items(避免缓存影响)
  const { items } = require("./items");
  expect(items[0].name).toBe("Android");
});

it("should be ios", () => {
  jest.mock("@my/utils", () => ({ isIOS: true }));
  const { items } = require("./items");
  expect(items[0].name).toBe("Apple");
});

如果希望isIOS的Mock值和Platform.OS联动,也可以用动态getter:

// 全局Mock utils模块
jest.mock("@my/utils", () => ({
  get isIOS() {
    return jest.requireActual("react-native").Platform.OS === "ios";
  },
}));

it("should be android", () => {
  // 仅Mock Platform.OS
  jest.spyOn(require("react-native").Platform, "OS", "get").mockReturnValue("android");
  const { items } = require("./items");
  expect(items[0].name).toBe("Android");
});

2. 使用jest.isolateModules隔离模块导入

jest.isolateModules会创建一个隔离的模块上下文,自动处理模块缓存的重置,比手动调用jest.resetModules()更简洁:

it("should be android", () => {
  jest.isolateModules(() => {
    // 在隔离环境中修改Platform.OS
    jest.spyOn(require("react-native").Platform, "OS", "get").mockReturnValue("android");
    // 导入的模块不会和其他测试用例共享缓存
    const { items } = require("./items");
    expect(items[0].name).toBe("Android");
  });
});

it("should be ios", () => {
  jest.isolateModules(() => {
    jest.spyOn(require("react-native").Platform, "OS", "get").mockReturnValue("ios");
    const { items } = require("./items");
    expect(items[0].name).toBe("Apple");
  });
});

3. 重构代码提升可测试性(长期推荐)

从根源解决问题的方式是重构静态常量为可注入的逻辑,让测试更灵活:

修改utils.ts:

import { Platform } from "react-native";
// 将静态常量改为可传入自定义Platform的函数
export const getIsIOS = (platform = Platform) => platform.OS === "ios";

修改items.ts:

import { getIsIOS } from "@my/utils";
// 保留原导出用于业务代码
export const items = [{
  id: 1,
  name: getIsIOS() ? "Apple" : "Android"
}];
// 新增带参数的版本用于测试
export const getItems = (platform?: any) => [{
  id: 1,
  name: getIsIOS(platform) ? "Apple" : "Android"
}];

测试代码:

import { getItems } from "./items";

it("should be android", () => {
  const items = getItems({ OS: "android" });
  expect(items[0].name).toBe("Android");
});

it("should be ios", () => {
  const items = getItems({ OS: "ios" });
  expect(items[0].name).toBe("Apple");
});

这种方式无需依赖Jest的Mock API,测试逻辑更清晰,也提升了代码的灵活性。

内容的提问来源于stack exchange,提问作者Aure77

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:37:43