Update:
所有这些信息和更多信息现已添加到新指南中的 Jest 文档中,“ES6 类模拟 https://facebook.github.io/jest/docs/en/es6-class-mocks.html."
完全披露:我写的。 :-)
模拟 ES6 类的关键是要知道ES6 类是一个函数。所以,模拟也必须是一个函数.
- Call
jest.mock('./mocked-class.js');
,并导入“./mocked-class.js”。
- 对于要跟踪调用的任何类方法,创建一个指向模拟函数的变量,如下所示:
const mockedMethod = jest.fn();
。在下一步中使用它们。
- Call
MockedClass.mockImplementation()
。传入一个箭头函数,该函数返回一个包含任何模拟方法的对象,每个方法设置为自己的模拟函数(在步骤 2 中创建)。
- 可以使用手动模拟(__mocks__ 文件夹)来模拟 ES6 类来完成同样的事情。在这种情况下,导出的模拟是通过调用创建的
jest.fn().mockImplementation()
,与上面 (3) 中描述的参数相同。这将创建一个模拟函数。在这种情况下,您还需要导出您想要监视的任何模拟方法。
- 可以通过调用来完成同样的事情
jest.mock('mocked-class.js', factoryFunction)
,其中,factoryFunction 又是上面 3 和 4 中传递的相同参数。
一个例子抵得上一千个字,所以这里是代码。
此外,这里还有一个演示所有这些的存储库:https://github.com/jonathan-stone/jest-es6-classes-demo/tree/mocks-working https://github.com/jonathan-stone/jest-es6-classes-demo/tree/mocks-working
首先,对于你的代码
如果您要添加以下设置代码,您的测试应该会通过:
const connectMock = jest.fn(); // Lets you check if `connect()` was called, if you want
Socket.mockImplementation(() => {
return {
connect: connectMock
};
});
(注意,在您的代码中:Socket.mock.calls[0][1]
应该[0][0]
, and [0][2]
应该[0][1]
. )
接下来,一个人为的例子
内嵌一些解释。
模拟类.js。请注意,测试期间永远不会调用此代码。
export default class MockedClass {
constructor() {
console.log('Constructed');
}
mockedMethod() {
console.log('Called mockedMethod');
}
}
模拟类consumer.js。此类使用模拟类创建一个对象。我们希望它创建一个模拟版本而不是真实版本。
import MockedClass from './mocked-class';
export default class MockedClassConsumer {
constructor() {
this.mockedClassInstance = new MockedClass('yo');
this.mockedClassInstance.mockedMethod('bro');
}
}
模拟类consumer.test.js- 考试:
import MockedClassConsumer from './mocked-class-consumer';
import MockedClass from './mocked-class';
jest.mock('./mocked-class'); // Mocks the function that creates the class; replaces it with a function that returns undefined.
// console.log(MockedClass()); // logs 'undefined'
let mockedClassConsumer;
const mockedMethodImpl = jest.fn();
beforeAll(() => {
MockedClass.mockImplementation(() => {
// Replace the class-creation method with this mock version.
return {
mockedMethod: mockedMethodImpl // Populate the method with a reference to a mock created with jest.fn().
};
});
});
beforeEach(() => {
MockedClass.mockClear();
mockedMethodImpl.mockClear();
});
it('The MockedClassConsumer instance can be created', () => {
const mockedClassConsumer = new MockedClassConsumer();
// console.log(MockedClass()); // logs a jest-created object with a mockedMethod: property, because the mockImplementation has been set now.
expect(mockedClassConsumer).toBeTruthy();
});
it('We can check if the consumer called the class constructor', () => {
expect(MockedClass).not.toHaveBeenCalled(); // Ensure our mockClear() is clearing out previous calls to the constructor
const mockedClassConsumer = new MockedClassConsumer();
expect(MockedClass).toHaveBeenCalled(); // Constructor has been called
expect(MockedClass.mock.calls[0][0]).toEqual('yo'); // ... with the string 'yo'
});
it('We can check if the consumer called a method on the class instance', () => {
const mockedClassConsumer = new MockedClassConsumer();
expect(mockedMethodImpl).toHaveBeenCalledWith('bro');
// Checking for method call using the stored reference to the mock function
// It would be nice if there were a way to do this directly from MockedClass.mock
});