이것이 불가능하다고 생각하기 시작했지만 어쨌든 묻고 싶습니다.
ES6 모듈 중 하나가 특정 방식으로 다른 ES6 모듈을 호출하는지 테스트하고 싶습니다. Jasmine을 사용하면 매우 쉽습니다.
앱 코드 :
// myModule.js
import dependency from './dependency';
export default (x) => {
dependency.doSomething(x * 2);
}
그리고 테스트 코드 :
//myModule-test.js
import myModule from '../myModule';
import dependency from '../dependency';
describe('myModule', () => {
it('calls the dependency with double the input', () => {
spyOn(dependency, 'doSomething');
myModule(2);
expect(dependency.doSomething).toHaveBeenCalledWith(4);
});
});
Jest와 동등한 것은 무엇입니까? 나는 이것이 그렇게하고 싶은 단순한 일이라고 생각하지만, 그것을 알아 내려고 노력하면서 머리카락을 찢어 버렸습니다.
내가 가장 가까운 것은 import
s를 require
s 로 바꾸고 테스트 / 함수 내부로 옮기는 것입니다. 어느 쪽도 내가하고 싶은 일이 아닙니다.
// myModule.js
export default (x) => {
const dependency = require('./dependency'); // yuck
dependency.doSomething(x * 2);
}
//myModule-test.js
describe('myModule', () => {
it('calls the dependency with double the input', () => {
jest.mock('../dependency');
myModule(2);
const dependency = require('../dependency'); // also yuck
expect(dependency.doSomething).toBeCalledWith(4);
});
});
보너스 포인트의 경우 내부 함수 dependency.js
가 기본 내보내기 일 때 모든 것이 작동하도록하고 싶습니다 . 그러나 기본 수출에 대한 감시가 Jasmine에서 작동하지 않거나 적어도 작동하지 않을 수 있다는 것을 알고 있으므로 Jest에서도 가능하다는 희망을 가지고 있지 않습니다.
답변
관련 해킹을 사용하여이 문제를 해결할 수있었습니다 import *
. 명명 된 내보내기와 기본 내보내기 모두에서 작동합니다!
명명 된 내보내기의 경우 :
// dependency.js
export const doSomething = (y) => console.log(y)
// myModule.js
import { doSomething } from './dependency';
export default (x) => {
doSomething(x * 2);
}
// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';
describe('myModule', () => {
it('calls the dependency with double the input', () => {
dependency.doSomething = jest.fn(); // Mutate the named export
myModule(2);
expect(dependency.doSomething).toBeCalledWith(4);
});
});
또는 기본 내보내기의 경우 :
// dependency.js
export default (y) => console.log(y)
// myModule.js
import dependency from './dependency'; // Note lack of curlies
export default (x) => {
dependency(x * 2);
}
// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';
describe('myModule', () => {
it('calls the dependency with double the input', () => {
dependency.default = jest.fn(); // Mutate the default export
myModule(2);
expect(dependency.default).toBeCalledWith(4); // Assert against the default
});
});
Mihai Damian이 아래에서 올바르게 지적했듯이 이것은의 모듈 객체를 변경 dependency
하고 있으므로 다른 테스트로 ‘누설’됩니다. 따라서이 방법을 사용하면 원래 값을 저장 한 다음 각 테스트 후에 다시 설정해야합니다. Jest로 쉽게 수행하려면 spyOn ()을 사용하십시오.jest.fn()
원래 값 복원을 쉽게 지원하므로 앞에서 언급 한 ‘누출’을 피하기 때문에 메서드를 사용하십시오 .
답변
모듈을 조롱하고 스파이를 직접 설정해야합니다.
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
doSomething: jest.fn()
}))
describe('myModule', () => {
it('calls the dependency with double the input', () => {
myModule(2);
expect(dependency.doSomething).toBeCalledWith(4);
});
});
답변
jest를 사용하여 ES6 종속성 모듈 기본 내보내기를 조롱하려면 다음을 수행하십시오.
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');
// If necessary, you can place a mock implementation like this:
dependency.mockImplementation(() => 42);
describe('myModule', () => {
it('calls the dependency once with double the input', () => {
myModule(2);
expect(dependency).toHaveBeenCalledTimes(1);
expect(dependency).toHaveBeenCalledWith(4);
});
});
다른 옵션은 제 경우에는 효과가 없었습니다.
답변
Andreas 답변에 더 추가. ES6 코드와 동일한 문제가 있었지만 가져 오기를 변경하고 싶지 않았습니다. 해키처럼 보였다. 그래서 나는 이것을했다
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');
describe('myModule', () => {
it('calls the dependency with double the input', () => {
myModule(2);
});
});
그리고 “__ mocks __”폴더에 dependency.js와 병행하여 dependency.js를 추가했습니다. 이것은 나를 위해 일했습니다. 또한 이것은 모의 구현에서 적합한 데이터를 반환 할 수있는 옵션을 제공했습니다. 조롱하려는 모듈의 올바른 경로를 제공하십시오.
답변
2020 년으로 빨리 넘어 가면서이 링크가 해결책이라는 것을 알았습니다. ES6 모듈 구문 만 사용 https://remarkablemark.org/blog/2018/06/28/jest-mock-default-named-export/
// esModule.js
export default 'defaultExport';
export const namedExport = () => {};
// esModule.test.js
jest.mock('./esModule', () => ({
__esModule: true, // this property makes it work
default: 'mockedDefaultExport',
namedExport: jest.fn(),
}));
import defaultExport, { namedExport } from './esModule';
defaultExport; // 'mockedDefaultExport'
namedExport; // mock function
또한 당신이 알아야 할 한 가지는 (내가 알아내는 데 시간이 걸렸다) 테스트 내에서 jest.mock ()을 호출 할 수 없다는 것입니다. 모듈의 최상위 레벨에서 호출해야합니다. 그러나 테스트마다 다른 모의 객체를 설정하려면 개별 테스트 내에서 mockImplementation ()을 호출 할 수 있습니다.
답변
질문에 이미 답변되었지만 다음과 같이 해결할 수 있습니다.
dependency.js
const doSomething = (x) => x
export default doSomething;
myModule.js :
import doSomething from "./dependency";
export default (x) => doSomething(x * 2);
myModule.spec.js :
jest.mock('../dependency');
import doSomething from "../dependency";
import myModule from "../myModule";
describe('myModule', () => {
it('calls the dependency with double the input', () => {
doSomething.mockImplementation((x) => x * 10)
myModule(2);
expect(doSomething).toHaveBeenCalledWith(4);
console.log(myModule(2)) // 40
});
});
답변
나는 이것을 다른 방법으로 해결했다. 의존성이 있다고 가정 해 봅시다.
export const myFunction = () => { }
다음 내용으로 depdency.mock.js 파일을 만듭니다.
export const mockFunction = jest.fn();
jest.mock('dependency.js', () => ({ myFunction: mockFunction }));
테스트에서 내가 사용하는 depedency가있는 파일을 가져 오기 전에 :
import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'
it('my test', () => {
mockFunction.returnValue(false);
functionThatCallsDep();
expect(mockFunction).toHaveBeenCalled();
})