我想测试我的一个ES6模块以特定的方式调用另一个ES6模块。对贾斯敏来说,这非常简单
应用程序代码:
// 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对应的是什么?我觉得这是一件很简单的事情,但我一直在努力想弄清楚。
我最接近的方法是用require替换导入,并将它们移动到测试/函数中。这两件事我都不想做。
// 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中也能做到这一点不抱希望。
我尝试了所有的解决方案,没有一个工作或显示大量的TS错误。
我是这样解决的:
格式。ts文件:
import camelcaseKeys from 'camelcase-keys'
import parse from 'xml-parser'
class Format {
parseXml (xml: string) {
return camelcaseKeys(parse(xml), {
deep: true,
})
}
}
const format = new Format()
export { format }
format.test.ts文件:
import format from './format'
import camelcaseKeys from 'camelcase-keys'
import parse from 'xml-parser'
jest.mock('xml-parser', () => jest.fn().mockReturnValue('parsed'))
jest.mock('camelcase-keys', () => jest.fn().mockReturnValue('camel cased'))
describe('parseXml', () => {
test('functions called', () => {
const result = format.parseXml('XML')
expect(parse).toHaveBeenCalledWith('XML')
expect(camelcaseKeys).toHaveBeenCalledWith('parsed', { deep: true })
expect(result).toBe('camel cased')
})
})
这里的答案似乎都不适合我(原始函数总是被导入,而不是mock),而且Jest中的ESM支持似乎仍在进行中。
在发现这条注释之后,我发现joke .mock()实际上不能与常规导入一起工作,因为导入总是在mock之前运行(现在也正式记录了这一点)。因此,我使用await import()导入我的依赖项。这甚至适用于顶级的等待,所以我只需要调整我的导入:
import { describe, expect, it, jest } from '@jest/globals';
jest.unstable_mockModule('../dependency', () => ({
doSomething: jest.fn()
}));
const myModule = await import('../myModule');
const dependency = await import('../dependency');
describe('myModule', async () => {
it('calls the dependency with double the input', () => {
myModule(2);
expect(dependency.doSomething).toBeCalledWith(4);
});
});
我用另一种方法解决了这个问题。假设你有依赖项。js
export const myFunction = () => { }
我在它之外创建了一个dependency .mock.js文件,内容如下:
export const mockFunction = jest.fn();
jest.mock('dependency.js', () => ({ myFunction: mockFunction }));
在测试中,在导入有依赖关系的文件之前,我使用:
import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'
it('my test', () => {
mockFunction.returnValue(false);
functionThatCallsDep();
expect(mockFunction).toHaveBeenCalled();
})