Nice programing

모듈이 모의 해제되었을 때 Jest에서 가져온 명명 된 함수를 모의하는 방법

nicepro 2020. 12. 30. 20:22
반응형

모듈이 모의 해제되었을 때 Jest에서 가져온 명명 된 함수를 모의하는 방법


Jest에서 테스트하려는 다음 모듈이 있습니다.

// myModule.js

export function otherFn() {
  console.log('do something');
}

export function testFn() {
  otherFn();

  // do other things
}

위와 같이, 그것은 중요한 일부라는 이름의 함수와 수출 testFn용도 otherFn.

Jest에서에 대한 단위 테스트를 작성할 때 .에 대한 단위 테스트에 영향을 미치는 오류를 원하지 않기 때문에 함수 testFn를 조롱하고 otherFn싶습니다 . 내 문제는이를 수행하는 가장 좋은 방법이 확실하지 않다는 것입니다.otherFntestFn

// myModule.test.js
jest.unmock('myModule');

import { testFn, otherFn } from 'myModule';

describe('test category', () => {
  it('tests something about testFn', () => {
    // I want to mock "otherFn" here but can't reassign
    // a.k.a. can't do otherFn = jest.fn()
  });
});

모든 도움 / 통찰을 주시면 감사하겠습니다.


jest.requireActual()내부 사용jest.mock()

jest.requireActual(moduleName)

모의 구현을 수신해야하는지 여부에 대한 모든 검사를 무시하고 모의 대신 실제 모듈을 반환합니다.

반환 된 객체 내에서 필요하고 확산되는이 간결한 사용법을 선호합니다.

// myModule.test.js

jest.mock('./myModule.js', () => (
  {
    ...(jest.requireActual('./myModule.js')),
    otherFn: () => {}
  }
))

describe(...)

이 방법은 Jest의 Manual Mocks 문서 ( Examples 의 끝 부분에 있음 ) 에서도 참조됩니다 .

수동 모의와 실제 구현이 동기화 상태를 유지하려면 jest.requireActual(moduleName)수동 모의에서 사용하는 실제 모듈을 요구하고 내보내기 전에 모의 함수로 수정하는 것이 유용 할 수 있습니다 .


import m from '../myModule';

나를 위해 작동하지 않으며 다음을 사용했습니다.

import * as m from '../myModule';

m.otherFn = jest.fn();

이 파티에 늦는 것 같지만 가능합니다.

testFnotherFn 모듈을 사용하여 호출 하면 됩니다.

경우 testFn사용하는 모듈이 호출 otherFn다음에 대한 모듈 수출 otherFn조롱 할 수 및 testFn모의를 호출합니다.


다음은 작동하는 예입니다.

myModule.js

import * as myModule from './myModule';  // import myModule into itself

export function otherFn() {
  return 'original value';
}

export function testFn() {
  const result = myModule.otherFn();  // call otherFn using the module

  // do other things

  return result;
}

myModule.test.js

import * as myModule from './myModule';

describe('test category', () => {
  it('tests something about testFn', () => {
    const mock = jest.spyOn(myModule, 'otherFn');  // spy on otherFn
    mock.mockReturnValue('mocked value');  // mock the return value

    expect(myModule.testFn()).toBe('mocked value');  // SUCCESS

    mock.mockRestore();  // restore otherFn
  });
});

트랜스 파일 된 코드는 babel otherFn()이 참조 하는 바인딩을 검색하는 것을 허용하지 않습니다 . 함수 expession을 사용하면 mocking을 얻을 수 있습니다 otherFn().

// myModule.js
exports.otherFn = () => {
  console.log('do something');
}

exports.testFn = () => {
  exports.otherFn();

  // do other things
}

 

// myModule.test.js
import m from '../myModule';

m.otherFn = jest.fn();

그러나 @kentcdodds가 이전 주석에서 언급했듯이, 아마도 mock을 원하지 않을 것입니다 otherFn(). 오히려 새로운 사양을 작성하고 otherFn()필요한 호출을 모의합니다.

예를 들어 otherFn()http 요청을하는 경우 ...

// myModule.js
exports.otherFn = () => {
  http.get('http://some-api.com', (res) => {
    // handle stuff
  });
};

여기서 모의 http.get구현을 기반으로 어설 션 을 모의 하고 업데이트 할 수 있습니다.

// myModule.test.js
jest.mock('http', () => ({
  get: jest.fn(() => {
    console.log('test');
  }),
}));

여기의 첫 번째 답변 외에도 babel-plugin-rewire 를 사용하여 가져온 명명 된 함수를 모의 할 수도 있습니다 . 이름이 지정된 함수 재배 선에 대한 섹션을 표면적으로 확인할 수 있습니다 .

One of the immediate benefits for your situation here is that you do not need to change how you call the other function from your function.


I know this was asked a long time ago, but I just ran into this very situation and finally found a solution that would work. So I thought I'd share here.

For the module:

// myModule.js

export function otherFn() {
  console.log('do something');
}

export function testFn() {
  otherFn();

  // do other things
}

You can change to the following:

// myModule.js

export const otherFn = () => {
  console.log('do something');
}

export const testFn = () => {
  otherFn();

  // do other things
}

exporting them as a constants instead of functions. I believe the issue has to do with hoisting in JavaScript and using const prevents that behaviour.

Then in your test you can have something like the following:

import * as myModule from 'myModule';


describe('...', () => {
  jest.spyOn(myModule, 'otherFn').mockReturnValue('what ever you want to return');

  // or

  myModule.otherFn = jest.fn(() => {
    // your mock implementation
  });
});

Your mocks should now work as you would normally expect.

ReferenceURL : https://stackoverflow.com/questions/39755439/how-to-mock-imported-named-function-in-jest-when-module-is-unmocked

반응형