我开始认为这是不可能的,但无论如何我想问。
我想测试我的一个ES6模块以特定方式调用另一个ES6模块。使用Jasmine,这非常容易 -
应用代码:
//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);
});
});
测试代码:
import
与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);
});
});
s,并将它们移到测试/函数中。这些都不是我想要做的事情。
dependency.js
对于奖励积分,当var Post = new mongoose.Schema({
name:String,
post:[{
like:String,
comment:[{
date:String,
username:String,
detail:{
time:String,
day:String
}
}]
}]
})
内的函数是默认导出时,我很乐意让整个事情发挥作用。但是,我知道监视默认导出在Jasmine中不起作用(或者至少我永远无法使用它),所以我并不是希望Jest中也可以这样做。
答案 0 :(得分:167)
我已经能够通过使用涉及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()
,因为它支持轻松恢复其原始值,因此避免在提及“泄漏”之前。
答案 1 :(得分:118)
你必须自己模拟模块并设置间谍:
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);
});
});
答案 2 :(得分:37)
为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);
});
});
并在"中添加了dependency.js。 __ 模拟 __"与dependency.js并行的文件夹。这对我有用。此外,这使我可以选择从模拟实现中返回合适的数据。确保为要模拟的模块提供正确的路径。
答案 3 :(得分:29)
快速前进到2020年,我发现此博客文章是解决方案: Jest mock default and named export
仅使用ES6模块语法:
// 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()。
答案 4 :(得分:0)
我用另一种方式解决了这个问题。假设您有dependency.js
export const myFunction = () => { }
除以下内容外,我还创建了一个depdency.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();
})
答案 5 :(得分:0)
问题已经回答,但是您可以这样解决:
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
});
});