[英]Mocking classes in Jest does not call the same method
我正在尝试模拟一个 class ,该 class 正在使用require
导入我的代码,然后测试该 class 的方法是否被调用。
我创建了一个示例设置,可以在其中复制此问题:
// user.js
class User {
getName() {
return "Han Solo"
}
}
module.exports = User
// user-consumer.js
const User = require('./user')
const user = new User()
module.exports.getUserName = () => {
// do things here
return user.getName()
}
// user.test.js
const userConsumer = require('./user-consumer')
const User = require('./user')
jest.mock('./user')
it('should mock', () => {
const user = new User()
jest.spyOn(user, 'getName')
userConsumer.getUserName()
expect(user.getName).toBeCalled()
})
我得到的错误如下:
如果我使用 ES6 语法,这将在 jest 的文档中显示: https://jestjs.io/docs/en/es6-class-mocks
但不幸的是,我不能在这个项目上使用 ES6,因为它需要大量的重构。
我还用模块出厂参数试过mocking class
jest.mock('./user', () => {
return jest.fn(() => {
return {
getName: jest.fn(),
}
})
})
它仍然不起作用。 当我在user-consumer.js:5
中记录console.log(user.getName)
时,它确实表明该方法已被模拟,但在user.getName()
中调用的不是消费者 function 仍然返回“Han Solo”。
我也尝试过使用和不jest.spyOn
,它仍然返回相同的错误。
这在没有 ES6 语法的情况下是不可能的吗?
问题是 Jest 间谍有无证行为。
即使所有实例的原型方法都相同:
new User().getName === new User().getName
间谍特定于一个实例:
jest.spyOn(new User(), 'getName') !== jest.spyOn(new User(), 'getName')
如果一个特定的实例是不可访问的,它是一个需要被窥探的原型:
jest.spyOn(User.prototype, 'getName')
userConsumer.getUserName()
expect(User.prototype.getName).toBeCalled();
jest.mock
的问题并非特定于 ES6 语法。 为了让 spy 可用于断言和实现更改,它应该暴露在某个地方。 在jest.mock
工厂之外声明它不是一个好的解决方案,因为它通常会导致手册中描述的竞争条件; 在这种情况下也会有一个。 一种更安全的方法是将引用公开为模块模拟的一部分。
ES 模块会更直接,因为这样 class 导出是分开保存的:
import MockedUser, { mockGetName } from './user';
jest.mock('./user', () => {
const mockGetName = jest.fn();
return {
__esModule: true,
mockGetName,
default: jest.fn(() => {
return {
getName: mockGetName
}
})
}
})
...
对于带有 class(函数)导出的 CommonJS 模块,它将被有效地暴露为 class static 方法:
import MockedUser from './user';
jest.mock('./user', () => {
const mockGetName = jest.fn();
return Object.assign(
jest.fn(() => {
return {
getName: mockGetName
}
}),
{ mockGetName }
})
})
...
MockedUser.mockGetName.mockImplementation(...);
userConsumer.getUserName()
expect(MockedUser.mockGetName).toBeCalled();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.