Jest 的 spyOn 期间出现类型错误:无法设置 #<Object> 的属性 getRequest它只有一个吸气剂 [英] TypeError during Jest's spyOn: Cannot set property getRequest of #<Object> which has only a getter

查看:13
本文介绍了Jest 的 spyOn 期间出现类型错误:无法设置 #<Object> 的属性 getRequest它只有一个吸气剂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 TypeScript 编写 React 应用程序.我使用 Jest 进行单元测试.

I'm writing a React application with TypeScript. I do my unit tests using Jest.

我有一个调用 API 的函数:

I have a function that makes an API call:

import { ROUTE_INT_QUESTIONS } from "../../../config/constants/routes";
import { intQuestionSchema } from "../../../config/schemas/intQuestions";
import { getRequest } from "../../utils/serverRequests";

const intQuestionListSchema = [intQuestionSchema];

export const getIntQuestionList = () => getRequest(ROUTE_INT_QUESTIONS, intQuestionListSchema);

getRequest 函数如下所示:

import { Schema } from "normalizr";
import { camelizeAndNormalize } from "../../core";

export const getRequest = (fullUrlRoute: string, schema: Schema) =>
  fetch(fullUrlRoute).then(response =>
    response.json().then(json => {
      if (!response.ok) {
        return Promise.reject(json);
      }
      return Promise.resolve(camelizeAndNormalize(json, schema));
    })
  );

我想像这样使用 Jest 尝试 API 函数:

I wanted to try the API function using Jest like this:

import fetch from "jest-fetch-mock";
import { ROUTE_INT_QUESTIONS } from "../../../config/constants/routes";
import {
  normalizedIntQuestionListResponse as expected,
  rawIntQuestionListResponse as response
} from "../../../config/fixtures";
import { intQuestionSchema } from "../../../config/schemas/intQuestions";
import * as serverRequests from "./../../utils/serverRequests";
import { getIntQuestionList } from "./intQuestions";

const intQuestionListSchema = [intQuestionSchema];

describe("getIntQuestionList", () => {
  beforeEach(() => {
    fetch.resetMocks();
  });

  it("should get the int question list", () => {
    const getRequestMock = jest.spyOn(serverRequests, "getRequest");
    fetch.mockResponseOnce(JSON.stringify(response));

    expect.assertions(2);
    return getIntQuestionList().then(res => {
      expect(res).toEqual(expected);
      expect(getRequestMock).toHaveBeenCalledWith(ROUTE_INT_QUESTIONS, intQuestionListSchema);
    });
  });
});

问题是带有 spyOn 的那行抛出以下错误:

The problem is that the line with spyOn throws the following error:

  ● getRestaurantList › should get the restaurant list

    TypeError: Cannot set property getRequest of #<Object> which has only a getter

      17 |
      18 |   it("should get the restaurant list", () => {
    > 19 |     const getRequestMock = jest.spyOn(serverRequests, "getRequest");
         |                                 ^
      20 |     fetch.mockResponseOnce(JSON.stringify(response));
      21 |
      22 |     expect.assertions(2);

      at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:706:26)
      at Object.spyOn (src/services/api/IntQuestions/intQuestions.test.ts:19:33)

我用谷歌搜索了这个,只找到了关于热重载的帖子.那么在 Jest 测试期间是什么导致了这种情况呢?我怎样才能通过这个测试?

I googled this and only found posts about hot reloading. So what could cause this during Jest test? How can I get this test to pass?

推荐答案

这个很有趣.

Babel 生成的属性只为重新导出的函数定义了 get.

Babel generates properties with only get defined for re-exported functions.

utils/serverRequests/index.ts 从其他模块重新导出函数,因此当 jest.spyOn 用于监视重新导出的函数时会抛出错误.

utils/serverRequests/index.ts re-exports functions from other modules so an error is thrown when jest.spyOn is used to spy on the re-exported functions.

鉴于此代码从 lib 重新导出所有内容:

Given this code re-exporting everything from lib:

export * from './lib';

...Babel 产生这个:

'use strict';

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

var _lib = require('./lib');

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

注意,所有的属性都是用get定义的.

Note that the properties are all defined with only get.

尝试对这些属性中的任何一个使用 jest.spyOn 将产生您看到的错误,因为 jest.spyOn 尝试用包裹原始属性的 spy 替换该属性函数,但如果属性仅用 get 定义,则不能.

Trying to use jest.spyOn on any of those properties will generate the error you are seeing because jest.spyOn tries to replace the property with a spy wrapping the original function but can't if the property is defined with only get.

不是将 ../../utils/serverRequests(重新导出 getRequest)导入测试中,而是导入 getRequest 所在的模块code> 被定义并使用该模块来创建间谍.

Instead of importing ../../utils/serverRequests (which re-exports getRequest) into the test, import the module where getRequest is defined and use that module to create the spy.

按照@Volodymyr 和@TheF 的建议模拟整个 utils/serverRequests 模块

Mock the entire utils/serverRequests module as suggested by @Volodymyr and @TheF

这篇关于Jest 的 spyOn 期间出现类型错误:无法设置 #&lt;Object&gt; 的属性 getRequest它只有一个吸气剂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆