Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Jest中模拟类不会调用相同的方法_Javascript_Node.js_Unit Testing_Jestjs - Fatal编程技术网

Javascript 在Jest中模拟类不会调用相同的方法

Javascript 在Jest中模拟类不会调用相同的方法,javascript,node.js,unit-testing,jestjs,Javascript,Node.js,Unit Testing,Jestjs,我试图用require模拟一个导入到代码中的类,然后测试该类的方法是否被调用 我创建了一个示例设置,可以在其中复制此问题: //user.js 类用户{ getName(){ 回归“汉独奏” } } module.exports=用户 //user-consumer.js const User=require(“./User”) const user=新用户() module.exports.getUserName=()=>{ //在这里做事 返回user.getName() } //use

我试图用
require
模拟一个导入到代码中的类,然后测试该类的方法是否被调用

我创建了一个示例设置,可以在其中复制此问题:

//user.js
类用户{
getName(){
回归“汉独奏”
}
}
module.exports=用户
//user-consumer.js
const User=require(“./User”)
const user=新用户()
module.exports.getUserName=()=>{
//在这里做事
返回user.getName()
}
//user.test.js
const userConsumer=require(“./user consumer”)
const User=require(“./User”)
jest.mock('./用户')
它('should mock',()=>{
const user=新用户()
jest.spyOn(用户'getName')
userConsumer.getUserName()
expect(user.getName).toBeCalled()
})
我得到的错误如下:

如果我使用ES6语法,这将如jest的文档所示:

但不幸的是,我不能在这个项目上使用ES6,因为它需要大量的重构

我还尝试用modulefactory参数模拟该类

jest.mock('./user',()=>{
return jest.fn(()=>{
返回{
getName:jest.fn(),
}
})
})
它仍然不起作用。当我在
user consumer.js:5
中记录
console.log(user.getName)
时,它确实表明该方法已被模拟,但在
user.getName()
中调用的任何函数都不是,消费者函数仍然返回“Han Solo”

我也尝试过使用和不使用
jest.spyOn
时,它仍然返回相同的错误


如果没有ES6语法,这是不可能的吗?

问题是,Jest spies有未记录的行为

即使所有实例的原型方法相同:

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语法。为了使间谍可以用于断言和实现更改,它应该在某处公开。在
jest.mock
工厂之外声明它不是一个好的解决方案,因为它通常会导致中描述的竞争条件;在这种情况下也会有一个。更安全的方法是将引用公开为模块mock的一部分

对于ES模块来说更简单,因为这样可以单独保存类导出:

import MockedUser, { mockGetName } from './user';

jest.mock('./user', () => {
  const mockGetName = jest.fn();
  return {
    __esModule: true,
    mockGetName,
    default: jest.fn(() => {
      return {
        getName: mockGetName
      }
    })
  }
})
...
对于具有类(函数)导出的CommonJS模块,它将作为类静态方法有效公开:

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();

您已经到处使用ES6语法了。如果您指的是ES模块,请更具体一些。“这个问题并不是他们特有的。”埃斯特斯瓦克表示歉意。JS并不是我的强项;我误解了问题中的相关文件。我认为ES6语法在这里已经意味着使用
import
。我想说的是,我在这个例子中尝试使用了导入语法,它成功了。我知道我确实需要公开模拟函数引用,但我做得不对——在
jest.mock
之外声明它。这当然不起作用,因为
jest.mock
在定义变量之前运行。使用prototype和公开这样的函数对我都有效,你建议使用prototype方法吗?我想知道这是否会影响可能调用此方法的后续测试;jest.mock('./user',()=>{mockGetName=jest.fn()…。为了完整性,我列出了这两种方法,因为proto可以很好地监视/模拟原型方法。您可能需要jest.mock来模拟构造函数,这包括实例(箭头)方法。