모듈이 모의 해제되었을 때 Jest에서 가져온 명명 된 함수를 모의하는 방법 않기 때문에 기능을 otherFn내 단위 테스트에 영향을

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

// myModule.js

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

export function testFn() {
  otherFn();

  // do other things
}

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

나는 내 단위 테스트를 쓰고 있어요 때 농담으로 testFn, 나는 조롱 할 otherFn에 내가 오류를 원하지 않기 때문에 기능을 otherFn내 단위 테스트에 영향을 testFn. 내 문제는 최선의 방법이 확실하지 않다는 것입니다.

// 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: jest.fn()
  }
))

import { otherFn } from './myModule.js'

describe('test category', () => {
  it('tests something about otherFn', () => {
    otherFn.mockReturnValue('foo')
    expect(otherFn()).toBe('foo')
  })
})

이 방법은 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');
  }),
}));


답변

나는 이것이 오래 전에 요청되었다는 것을 알고 있지만, 바로이 상황에 부딪 쳤고 마침내 작동 할 해결책을 찾았습니다. 그래서 여기서 나눌 거라고 생각 했어요.

모듈의 경우 :

// myModule.js

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

export function testFn() {
  otherFn();

  // do other things
}

다음으로 변경할 수 있습니다.

// myModule.js

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

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

  // do other things
}

함수 대신 상수로 내보내기. 나는 문제가 JavaScript의 호이 스팅과 관련이 있다고 믿고 사용 const하면 그 동작 을 방지합니다.

그런 다음 테스트에서 다음과 같은 것을 가질 수 있습니다.

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

이제 모의가 평소 예상대로 작동합니다.


답변

여기에서 찾은 답변을 혼합하여 문제를 해결했습니다.

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', () => {
  let otherFnOrig;

  beforeAll(() => {
    otherFnOrig = myModule.otherFn;
    myModule.otherFn = jest.fn();
  });

  afterAll(() => {
    myModule.otherFn = otherFnOrig;
  });

  it('tests something about testFn', () => {
    // using mock to make the tests
  });
});


답변

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

여기서 상황에 대한 즉각적인 이점 중 하나는 함수에서 다른 함수를 호출하는 방법을 변경할 필요가 없다는 것입니다.