我尝试使用Jest
手动模拟来模拟使用的包X
的行为
在一个项目中。
在实际应用程序代码中使用包X
是这样的:
// Real.js
import X from '../lib/X.js';
export default class App {
...
execute() {
const x = new X(); // creating a new instance of X
x.doSomething(); // calling someThing() of X
}
...
}
我的 Jest手动模拟来模仿X
的行为,如下所示:
global.__test__X = () => ({
doSomething: jest.fn(async () => console.log('mocked async do something')),
id: (Math.random() * 1000) % 10,
});
module.exports = global.__test__X;
在我的测试中,我试图查看X被调用了多少次以及使用了什么参数 使用吹码:
jest.mock('../X');
import Real from '../Real';
const X = require('../X');
describe('Testing...', async () => {
it('DoSomething should print mocked console statement', async () => {
Real.execute(); // this would internally call X.doSomething()
const x = new X();
console.log(x.doSomething.mock.calls); // gives []
});
});
使用上面的内容,我试图查看X
被调用了多少次,但无法弄清楚是什么
我做错了,因为mock.calls
总是[]
。请注意,模拟正在进行中
执行,因为我可以看到mocked async do something
。
答案 0 :(得分:0)
使用jest.mock('./ SomeClass')进行此操作有完整的解释。适用于这个问题。 "ES6 class, Automatic mock"。 让我们开始吧。
// ./lib/X.js
export default class X {
constructor () {
this.id = '1234567890';
}
doSomething = () => {
return 'Original X';
}
}
注意,上面的代码从未在测试过程中调用过。
这是我们要测试的资源,我的意思是,在此类中,通过模拟的类或模块创建对象。我们要制作一个假的版本而不是原始的版本。
// Real.js
import X from './lib/X.js';
export default class App {
constructor() {
this.x = new X(); // creating a new instance of X
}
execute = () => {
this.x.doSomething(); // calling someThing() of X
}
}
接受一个函数,该函数应用作模拟的实现。因此,我们要做的是使用手动模拟(__模拟__文件夹)模拟ES6类。
// ./__mocks__/lib/X.js
module.exports = jest.fn().mockImplementation(() => {
return {
doSomething: jest.fn(() => 'Mocking Original X'),
id: (Math.random() * 1000) % 10
}
});
当我们在测试文件上import './lib/X.js'
时,现在,为了在不实际访问库的情况下测试此方法(从而创建缓慢而脆弱的测试),我们立即使用模拟'./lib/X.js'
模块
// Real.test.js
import X from './lib/X.js';
import Real from './Real';
jest.mock('./lib/X.js'); // // X module is now a mock constructor
describe('Testing', async () => {
beforeEach(() => {
// Clear all instances and calls to constructor and all methods:
X.mockClear();
});
it('DoSomething should print mocked correct statement', async () => {
// Ensure our mockClear() is clearing out previous calls to the constructor
expect(X).not.toHaveBeenCalled();
const real = new Real();
expect(X).toHaveBeenCalledTimes(1); // Constructor has been called X.js
real.execute();
// mock.instances is available with automatic mocks:
const mockXInstance = X.mock.instances[0];
const mockDoSomething = mockXInstance.doSomething;
expect(mockDoSomething).toHaveBeenCalledTimes(1);
expect(mockDoSomething.mock.calls[0][0]).toEqual('Mocking Original X');
});
});
也许这还不够回答,至少可以解释模拟在类似情况下的工作原理