programing

Jest spyOn: #Jest spyOn의 할 수 없습니다.TypeError: # 의 type type의 。Jest spyOn: #Jest spyOn의 할 수 없습니다.TypeError: # 의 type type의 。Jest spyOn: #Jest spyOn의 할 수 없습니다.TypeError: # 의 type type의 。게터밖..

easyjava 2023. 2. 23. 23:10
반응형

Jest spyOn: #Jest spyOn의 할 수 없습니다.TypeError: # 의 type type의 。게터밖에 없는

저는 TypeScript를 사용하여 React 어플리케이션을 작성하고 있습니다.나는 제스트를 사용하여 단위 테스트를 한다.

API를 호출하는 함수가 있습니다.

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 기능을 시도해보고 싶었습니다.

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는 다음 오류를 발생시킵니다.

  ● 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 테스트 중에 무엇이 이것을 야기할 수 있을까요?이 시험을 통과하려면 어떻게 해야 하나요?

이번 건 재밌었어요.

쟁점.

Babel다음에서만 속성을 생성합니다.get정의되어 있습니다.

utils/serverRequests/index.ts다른 모듈로부터 기능을 재실행하여 에러가 발생하도록 합니다.jest.spyOn를 사용하여 재인식 기능을 감시합니다.


세부 사항

이 코드를 지정하면 모든 것을 재내보내고 있습니다.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.

사용 시도 중jest.spyOn이러한 속성 중 하나에 대해 표시되는 오류가 발생합니다.jest.spyOn속성을 원래 함수를 감싸는 스파이로 바꾸려고 하지만 속성이 다음과 같이만 정의되어 있으면 바꿀 수 없습니다.get.


솔루션

Import 대신../../utils/serverRequests(그것은 재작성됩니다).getRequest테스트에 모듈을 Import 합니다.getRequest이 모듈을 사용하여 스파이를 만듭니다.

대체 솔루션

전체를 조롱하다utils/serverRequests@Volodymyr 및 @TheF에서 제안하는 모듈

코멘트에서 제시된 바와 같이, joke는 테스트 대상 오브젝트에 대해 es6 모듈오브젝트에 없는 세터를 필요로 합니다. jest.mock()를 사용하면 Import 후 필요한 모듈을 조롱함으로써 이 문제를 해결할 수 있습니다.

serverRequests 파일에서 내보내기를 비웃어 보십시오.

import * as serverRequests from './../../utils/serverRequests';
jest.mock('./../../utils/serverRequests', () => ({
    getRequest: jest.fn()
}));

// ...
// ...

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);
    });
});

다음은 유용한 링크입니다.
https://jestjs.io/docs/en/es6-class-mocks
https://jestjs.io/docs/en/mock-functions

테스트 대상ts-jest컴파일러로서 다음과 같이 모듈을 조롱하면 동작합니다.

import * as serverRequests from "./../../utils/serverRequests";

jest.mock('./../../utils/serverRequests', () => ({
  __esModule: true,
  ...jest.requireActual('./../../utils/serverRequests')
}));

const getRequestMock = jest.spyOn(serverRequests, "getRequest");

담당 의사의 농담:__esModule

최근에 우리가 사용하던 도서관에서 이런 일이 일어났어요.Babel은 라이브러리에서 내보낸 모든 멤버에게만 getter를 제공하고 있었기 때문에 테스트의 선두에서 이 작업을 수행했습니다.

jest.mock('some-library', () => ({
  ...jest.requireActual('some-library')
}));

이로 인해 라이브러리의 모든 속성에 대해 멤버가 포함된 일반 JS 개체가 새로 생성되었기 때문에 문제가 해결되었습니다.

이 문제가 있는 다른 사용자는 "느슨한" 변환을 사용하도록 babel을 설정하여 문제를 해결할 수 있습니다..babelrc 파일로 설정하기만 하면 됩니다.

{
  "presets": [
    ["@babel/preset-env", {
      "loose": true
    }]
  ]
}

Import를 변경하지 않고 그대로 두려면 다음과 같이 문제를 해결할 수 있습니다.

import * as lib from './lib'

jest.mock('./lib/subModule')

it('can be mocked', () => {
  jest.spyOn(lib, 'subModuleFunction')
})

넣어야 jest.mock감시하고 싶은 추가 재실행 기능에 대한 회선을 표시합니다.

Jest Unit-Test에서의 업그레이드는 다음 항목을 통과할 때 실패합니다.

export * from './serverRequests';

파일을 직접 참조하여 "...getter" 문제만 발생하지 않도록 하십시오.

언급URL : https://stackoverflow.com/questions/53162001/typeerror-during-jests-spyon-cannot-set-property-getrequest-of-object-which

반응형