Cam*_*son 227 javascript mocking node.js ecmascript-6 jestjs
我开始认为这是不可能的,但无论如何我想问.
我想测试我的一个ES6模块以特定方式调用另一个ES6模块.使用Jasmine这非常容易 -
应用代码:
// myModule.js
import dependency from './dependency';
export default (x) => {
dependency.doSomething(x * 2);
}
Run Code Online (Sandbox Code Playgroud)
和测试代码:
//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);
});
});
Run Code Online (Sandbox Code Playgroud)
什么与Jest相当?我觉得这是一件非常简单的事情,但我一直在试图弄清楚我的头发.
我最接近的import
是用require
s 替换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);
});
});
Run Code Online (Sandbox Code Playgroud)
对于奖励积分,当内部函数dependency.js
是默认导出时,我很乐意让整个过程完成.但是,我知道监视默认导出在Jasmine中不起作用(或者至少我无法让它工作),所以我并不是希望Jest中也可以.
Cam*_*son 187
我已经能够通过使用涉及的黑客来解决这个问题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);
});
});
Run Code Online (Sandbox Code Playgroud)
或者对于默认导出:
// 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
});
});
Run Code Online (Sandbox Code Playgroud)
正如Mihai Damian在下面正确地指出的那样,这正在改变模块对象dependency
,因此它将"泄漏"到其他测试中.因此,如果您使用此方法,则应存储原始值,然后在每次测试后重新设置.要使用Jest轻松完成此操作,请使用spyOn()方法,而不是jest.fn()
因为它支持轻松恢复其原始值,因此避免在提到"泄漏"之前.
And*_*rle 140
你必须自己模拟模块并设置间谍:
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);
});
});
Run Code Online (Sandbox Code Playgroud)
And*_*ndy 75
快进到 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
Run Code Online (Sandbox Code Playgroud)
还有一件事你需要知道(我花了一段时间才弄清楚)是你不能在测试中调用 jest.mock() ;您必须在模块的顶层调用它。但是,如果您想为不同的测试设置不同的模拟,您可以在单个测试中调用 mockImplementation()。
fal*_*lla 44
使用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);
});
});
Run Code Online (Sandbox Code Playgroud)
其他选项对我的情况不起作用.
mds*_*ubi 38
添加更多安德烈斯答案.我有与ES6代码相同的问题,但不想改变导入.看起来很丑陋.所以我这样做了
import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');
describe('myModule', () => {
it('calls the dependency with double the input', () => {
myModule(2);
});
});
Run Code Online (Sandbox Code Playgroud)
并在依赖于dependency.js的"__ mocks __"文件夹中添加了dependency.js.这对我有用.此外,这使我可以选择从模拟实现中返回合适的数据.确保为要模拟的模块提供正确的路径.
cda*_*uth 20
这里的答案似乎都不适合我(始终导入原始函数而不是模拟函数),并且 Jest 中的 ESM 支持似乎仍在进行中。
发现此评论后,我发现这jest.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);
});
});
Run Code Online (Sandbox Code Playgroud)
Sli*_*lim 11
问题已经回答了,但您可以这样解决:
const doSomething = (x) => x
export default doSomething;
Run Code Online (Sandbox Code Playgroud)
import doSomething from "./dependency";
export default (x) => doSomething(x * 2);
Run Code Online (Sandbox Code Playgroud)
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
});
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
143604 次 |
最近记录: |