16

我有UserContext一个useUsersrc/app/context/user-context.tsx. 此外,我有一个 index.tsx 文件,src/app/context其中导出所有子模块。

如果我 spyOnsrc/app/context/user-context它可以工作,但将导入更改为src/app/context我得到:

TypeError: Cannot redefine property: useUser at Function.defineProperty (<anonymous>)

这是为什么?

源代码:

// src/app/context/user-context.tsx

export const UserContext = React.createContext({});

export function useUser() {
  return useContext(UserContext);;
}

// src/app/context/index.tsx

export * from "./user-context";
// *.spec.tsx

// This works:
import * as UserContext from "src/app/context/user-context";

// This does not work:
// import * as UserContext from "src/app/context";

it("should render complete navigation when user is logged in", () => {

    jest.spyOn(UserContext, "useUser").mockReturnValue({
        user: mockUser,
        update: (user) => null,
        initialized: true,
    });
})
4

2 回答 2

7

如果您查看为重新导出而生成的 js 代码,它看起来像这样

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _context = require("context");

Object.keys(_context).forEach(function (key) {
  if (key === "default" || key === "__esModule") return;
  if (key in exports && exports[key] === _context[key]) return;
  Object.defineProperty(exports, key, {
    enumerable: true,
    get: function get() {
      return _context[key];
    }
  });
});

并且您得到的错误是由于编译器没有添加configurable: true选项defineProperty,这将允许 jest 从docs重新定义导出以模拟它

可配置

如果可以更改此属性描述符的类型并且可以从相应对象中删除该属性,则为 true。默认为false.

我认为您可以以某种方式调整配置以使编译器添加该配置,但这完全取决于您使用的工具。

一种更易于访问的方法是使用jest.mock而不是jest.spyOn模拟用户上下文文件,而不是尝试重新定义不可配置的导出

it("should render complete navigation when user is logged in", () => {
  jest.mock('./user-context', () => {
    return {
      ...jest.requireActual('./user-context'),
      useUser: jest.fn().mockReturnValue({
        user: {},
        update: (user: any) => null,
        initialized: true
      })
    }
  })
});

于 2021-11-13T05:28:25.590 回答
1

UserContextwhen re-exported from引发了这个app/context/index.tsx问题,因为它是 Typescript 在 3.9 之前的版本中如何处理重新导出的错误。

此问题在 3.9 版本中已修复,因此请将项目中的 Typescript 升级到此版本或更高版本。

此处报告了此问题,并通过此处的修复评论解决了此问题

以下是没有版本升级的解决方法。

在您的index.tsx文件中有一个具有属性的对象作为导入的方法,然后导出该对象。

里面src/app/context/index.tsx

import { useUser } from './context/user-context.tsx'

const context = {
  useUser,
  otherFunctionsIfAny
}

export default context;

或者这也应该有效,

import * as useUser from './context/user-context.tsx';

export { useUser };

export default useUser;

然后监视他们,

import * as UserContext from "src/app/context";

it("should render complete navigation when user is logged in", () => {

    jest.spyOn(UserContext, "useUser").mockReturnValue({
        user: mockUser,
        update: (user) => null,
        initialized: true,
    });
});

参考

很高兴知道:- 除了重新导出的问题外,以前的版本也不支持实时绑定,即,当导出模块发生更改时,导入模块无法看到导出端发生的更改。

前任:

测试.js

let num = 10;

function add() {
    ++num;  // Value is mutated
}

exports.num = num;
exports.add = add;

index.js

在此处输入图像描述

一个类似的问题,但由于导入的路径。

此错误消息(JavaScript)的原因在这篇文章中解释了TypeError: Cannot redefine property: Function.defineProperty ()

于 2021-11-12T15:48:34.783 回答