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

使用Jest模拟Next.js的appSettings模块时出现初始化前访问错误

解决Jest模拟Next.js appSettings模块时的ReferenceError问题

问题原因

你遇到的「ReferenceError: Cannot access '_appsettings' before initialization」错误,核心原因是Jest会自动把jest.mock调用提升到所有代码(包括import语句)的最顶部执行。你原本通过import导入的appSettings变量,在jest.mock的工厂函数执行时还未完成初始化,导致提前访问触发报错。

可行解决方案

方案1:在mock工厂函数中用require引入mock文件

把mock文件的引入放到jest.mock的工厂函数内部,利用require不会被Jest提升的特性,避免初始化顺序问题:

import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import { DonorSelector } from "../src/views/DonorSelector";

// 在mock工厂函数内用require加载mock对象
jest.mock("../src/helpers/app-settings.helper", () => ({
  ...require("../mocks/app-settings").appSettings,
}));

// 测试中需要用到mock值时,再正常导入
import { appSettings } from "../mocks/app-settings";

describe("DonorSelector", () => {
  it("should receive appSettings with mock values", () => {
    render(<DonorSelector content={content} setLanguageCallback={() => {}} />);
    
    expect(screen.getByTestId("app-settings")).toHaveTextContent(
      JSON.stringify(appSettings)
    );
  });
});

方案2:直接在mock工厂函数中定义mock对象

如果mock内容不复杂,可以直接把配置写在jest.mock的工厂函数里,省去单独导入的步骤:

import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import { DonorSelector } from "../src/views/DonorSelector";

// 直接在mock中定义appSettings的内容
jest.mock("../src/helpers/app-settings.helper", () => ({
  appSettings: {
    apiBaseUrl: "https://mock.example.com",
    defaultLocale: "zh-CN",
    // 其他你的配置项
  },
}));

// 从被mock的模块中导入,确保测试用的是同一个mock值
import { appSettings } from "../src/helpers/app-settings.helper";

describe("DonorSelector", () => {
  it("should receive appSettings with mock values", () => {
    render(<DonorSelector content={content} setLanguageCallback={() => {}} />);
    
    expect(screen.getByTestId("app-settings")).toHaveTextContent(
      JSON.stringify(appSettings)
    );
  });
});

方案3:使用jest.doMock避免自动提升(不推荐)

如果一定要保留单独的mock文件导入,可以用jest.doMock代替jest.mock,它不会被自动提升,需要确保在组件导入前执行:

import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import { appSettings } from "../mocks/app-settings";

// 用doMock替代mock,手动控制执行顺序
jest.doMock("../src/helpers/app-settings.helper", () => ({
  ...appSettings,
}));

// 必须在doMock之后再导入组件
const { DonorSelector } = require("../src/views/DonorSelector");

describe("DonorSelector", () => {
  it("should receive appSettings with mock values", () => {
    render(<DonorSelector content={content} setLanguageCallback={() => {}} />);
    
    expect(screen.getByTestId("app-settings")).toHaveTextContent(
      JSON.stringify(appSettings)
    );
  });
});

注意事项

  • 不要在jest.mock的工厂函数中直接引用任何被提升的import变量,因为Jest的mock提升机制会让这些变量在此时处于未初始化状态。
  • 优先使用方案1或方案2,这两种方式更符合Jest的常规使用习惯,代码可读性也更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:33:16