Jest를 사용하여 ES6 모듈 가져 오기를 어떻게 조롱 할 수 있습니까?
이것이 불가능하다고 생각하기 시작했지만 어쨌든 묻고 싶습니다.
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);
});
});
For bonus points, I'd love to make the whole thing work when the function inside dependency.js
is a default export. However, I know that spying on default exports doesn't work in Jasmine (or at least I could never get it to work), so I'm not holding out hope that it's possible in Jest either.
I've been able to solve this by using a hack involving import *
. It even works for both named and default exports!
For a named export:
// 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);
});
});
Or for a default export:
// 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
});
});
As Mihai Damian quite rightly pointed out below, this is mutating the module object of dependency
, and so it will 'leak' across to other tests. So if you use this approach you should store the original value and then set it back again after each test. To do this easily with Jest, use spyOn() method instead of jest.fn()
because it supports easily restoring its original value, therefore avoiding before mentioned 'leaking'.
You have to mock the module and set the spy by yourself:
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);
});
});
To mock an ES6 dependency module default export using jest:
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);
});
});
The other options didn't work for my case.
Adding more to Andreas answer. I had the same problem with ES6 code but did not want to mutate the imports. That looked hacky. So I did this
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');
describe('myModule', () => {
it('calls the dependency with double the input', () => {
myModule(2);
});
});
And added dependency.js in " __ mocks __" folder parallel to dependency.js. This worked for me. Also, this gave me option to return suitable data from mock implementation. Make sure you give the correct path to the module you want to mock.
I solved this another way. Let's say you have your dependency.js
export const myFunction = () => { }
I create a depdency.mock.js file besides it with the following content:
export const mockFunction = jest.fn();
jest.mock('dependency.js', () => ({ myFunction: mockFunction }));
and in the test, before I import the file that has the depedency I use:
import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'
it('my test', () => {
mockFunction.returnValue(false);
functionThatCallsDep();
expect(mockFunction).toHaveBeenCalled();
})
The question is already answered but you can resolve it like this:
dependency.js
module.exports.doSomething = (x) => x
myModule.js:
const { doSomething } = require('./dependency')
module.exports = (x) => doSomething(x * 2)
myModule.spec.js:
jest.mock('../dependency')
const { doSomething } = require('../dependency')
const myModule = require('../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
});
});
참고URL : https://stackoverflow.com/questions/40465047/how-can-i-mock-an-es6-module-import-using-jest
'Programing' 카테고리의 다른 글
변수가 클래스인지 아닌지 확인하는 방법? (0) | 2020.04.30 |
---|---|
PHP에서 yield는 무엇을 의미합니까? (0) | 2020.04.30 |
MySQL : DISTINCT 값 발생 횟수 계산 (0) | 2020.04.30 |
AngularJS에서 지시문을 동적으로 추가하려면 어떻게합니까? (0) | 2020.04.30 |
두 목록을 연결- '+ ='와 extend ()의 차이점 (0) | 2020.04.30 |