繁体   English   中英

Jest 中的 Mocking 类不调用相同的方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM