Javascript 在react钩子上调用时,jest.spyOn()TypeError

Javascript 在react钩子上调用时,jest.spyOn()TypeError,javascript,reactjs,typescript,react-hooks,react-testing-library,Javascript,Reactjs,Typescript,React Hooks,React Testing Library,我试图在测试中使用jest.spyOn(),而不是jest.mock,因为mock的返回值不能进行类型检查。但当我使用它时,会出现以下错误: TypeError: Cannot set property useGame of #<Object> which has only a getter > 3 | const STATE_SPY = jest.spyOn(hooks, "useGame"); | ^

我试图在测试中使用
jest.spyOn()
,而不是
jest.mock
,因为mock的返回值不能进行类型检查。但当我使用它时,会出现以下错误:

TypeError: Cannot set property useGame of #<Object> which has only a getter
> 3 | const STATE_SPY = jest.spyOn(hooks, "useGame");
    |                        ^ 
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:852:26)
at Object.<anonymous> (src/components/game/game.test.tsx:4:24)  
下面是我的代码的布局(我为这个问题删除了很多无关的代码) 使其更易于阅读)

/hooks/index.tsx

export { default as useGame } from "./use-game";
export default function useGame(initScore: number) {
  const [score, setScore] = useState(initScore);

  return {
    score,
    setScore,
  }
}
import * as hooks from "./hooks";

const STATE_SPY = jest.spyOn(hooks, "useGame");
import React from "react";
import { useGame } from "./hooks";

const STARTING_SCORE = 50;

export default function Game(): JSX.Element {
  const {score} = useGame(STARTING_SCORE);

  return (
    <div>
      {score}
    </div>
  )
}

使用game.tsx

export { default as useGame } from "./use-game";
export default function useGame(initScore: number) {
  const [score, setScore] = useState(initScore);

  return {
    score,
    setScore,
  }
}
import * as hooks from "./hooks";

const STATE_SPY = jest.spyOn(hooks, "useGame");
import React from "react";
import { useGame } from "./hooks";

const STARTING_SCORE = 50;

export default function Game(): JSX.Element {
  const {score} = useGame(STARTING_SCORE);

  return (
    <div>
      {score}
    </div>
  )
}

game.test.tsx

export { default as useGame } from "./use-game";
export default function useGame(initScore: number) {
  const [score, setScore] = useState(initScore);

  return {
    score,
    setScore,
  }
}
import * as hooks from "./hooks";

const STATE_SPY = jest.spyOn(hooks, "useGame");
import React from "react";
import { useGame } from "./hooks";

const STARTING_SCORE = 50;

export default function Game(): JSX.Element {
  const {score} = useGame(STARTING_SCORE);

  return (
    <div>
      {score}
    </div>
  )
}

game.tsx

export { default as useGame } from "./use-game";
export default function useGame(initScore: number) {
  const [score, setScore] = useState(initScore);

  return {
    score,
    setScore,
  }
}
import * as hooks from "./hooks";

const STATE_SPY = jest.spyOn(hooks, "useGame");
import React from "react";
import { useGame } from "./hooks";

const STARTING_SCORE = 50;

export default function Game(): JSX.Element {
  const {score} = useGame(STARTING_SCORE);

  return (
    <div>
      {score}
    </div>
  )
}


我查看了your package.json,发现包
@testing library/react hooks
已经在前面添加了。我建议使用它来编写钩子的新测试


您可以阅读文档开始

我查看了your package.json,发现包
@testing library/react hooks
已在前面添加。我建议使用它来编写钩子的新测试


您可以阅读文档开始

似乎您使用babel来传输代码。正如我所知,如果您使用通配符(名称空间)这样导入。它将创建一个对象,其中包含命名为getter-like的导出

var obj={get namedExport:()=>…}
因此,在这种情况下,我建议模拟整个模块:

jest.mock('./hooks',()=>({useGame:yourMock}))

或者切换到
tsc
,使用
ts jest
修复您的问题(因为
tsc
不会使用getter导出指定的导出)

似乎您使用babel来传输您的代码。正如我所知,如果您使用通配符(名称空间)这样导入。它将创建一个对象,其中包含命名为getter-like的导出

var obj={get namedExport:()=>…}
因此,在这种情况下,我建议模拟整个模块:

jest.mock('./hooks',()=>({useGame:yourMock}))

或者通过使用
ts jest
切换到
tsc
来解决您的问题(因为
tsc
不会使用getter导出指定的导出)

除非我弄错了,这是为了测试钩子本身。我已经为钩子本身编写了测试(因为它不相关,所以没有包含在我的问题中)。我想做的是在测试组件函数的同时监视钩子,看看单击按钮是否会导致钩子状态的改变。除非我弄错了,否则这是为了测试钩子本身。我已经为钩子本身编写了测试(因为它不相关,所以没有包含在我的问题中)。我想做的是在测试组件函数时监视钩子,看看单击按钮是否会导致钩子状态的更改。我想避免模拟,因为模拟的返回值不能进行类型检查。我安装了
ts jest
(24.3.0)并运行了
npx ts jest-config:init
。但是当我运行
npm测试时,我得到了完全相同的错误。记录
hooks
会给出
{useGame:[Getter]}
hooks。useGame
[Function:useGame]
的形式记录,找到了一个有效的解决方案。将其改写为:
import*as useGame from.“/hooks/use game”
const STATE\u SPY=jest.spyOn(使用游戏,“默认”)
useGame
记录为
{default:[函数:useGame]}
当这起作用时,对于样式点,我更喜欢从由
index.tsx
创建的模块导入的解决方案,因为这是导入其他所有内容的方式。我希望避免模拟,因为无法检查模拟的返回值。我安装了
ts jest
(24.3.0)并运行了
npx ts jest-config:init
。但是当我运行
npm测试时,我得到了完全相同的错误。记录
hooks
会给出
{useGame:[Getter]}
hooks。useGame
[Function:useGame]
的形式记录,找到了一个有效的解决方案。将其改写为:
import*as useGame from.“/hooks/use game”
const STATE\u SPY=jest.spyOn(使用游戏,“默认”)
useGame
记录为
{default:[函数:useGame]}
当这起作用时,对于样式点,我更喜欢从由
index.tsx
创建的模块导入的解决方案,因为其他所有内容都是这样导入的。