【问题标题】:Cannot mock react-native-sound with Jest无法用 Jest 模拟 react-native-sound
【发布时间】:2018-05-05 16:53:41
【问题描述】:

当我尝试用 Jest 模拟 react-native-sound 时,我收到以下错误:

//PlayerService.js
import Sound from 'react-native-sound';

try {
  console.log('Sound: ' + JSON.stringify(Sound)); //Sound: {}
  _trackPlaying = new Sound('path', Sound.LIBRARY, error => { });
} catch (error) {
  console.log('error: ' + JSON.stringify(error)); //error: {}
}
//PlayerService.tests.js
jest.mock('react-native-sound', () => ({
  Sound: jest.fn((path, type, callback) => {

  })
}));

// package.json

{
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-jest": "^21.2.0",
    "babel-plugin-transform-flow-strip-types": "^6.22.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-flow": "^6.23.0",
    "flow": "^0.2.3",
    "jest": "^21.2.1"
  },
  "jest": {
    "modulePathIgnorePatterns": [
      "__mocks__/"
    ]
  },
  "dependencies": {
    "react-native-sound": "^0.10.4"
  }
}

或者,我尝试在一个单独的文件(__mock__ 文件夹)中设置手动模拟,但运气相似:

//__mocks__/react-native-sound.js
const Sound = jest.genMockFromModule('react-native-sound');

Sound = (path, type, callback) => {
  console.log("mocked");
}

module.exports = Sound;

//__tests__/PlayerService.tests.js
jest.mock('react-native-sound'); // doesn't work

任何指导或建议将不胜感激。非常感谢!

【问题讨论】:

  • 也许你还需要模拟Sound.LIBRARY
  • 在这个例子中没有,但我做到了。我没有做的是模拟正在导出的任何内容。我要试试。
  • 您遇到的错误是什么?我似乎在你的问题中找不到它。
  • 错误显示为注释://error: {}。但我终于弄清楚了错误是什么。

标签: reactjs unit-testing react-native mocking jestjs


【解决方案1】:

您必须模拟您正在使用的所有功能。您制作的模拟并未提供您需要的所有功能。您需要模拟 Sound 的构造函数,因为您正在创建一个,您需要模拟 Sound.LIBRARY 因为您也在使用它。此外,您需要制作的模拟非常简单,我不会费心使用 genMockFromModule 它更多的是用于扩展模块。只需自己实现一个简单的模拟,它就可以让您更好地控制模块的实际功能。由于您使用的是 babel 和 ES6,我只会将其模拟为一个类并模拟您使用的所有函数。

类似的东西。 . .

// __mocks__/react-native-sound.js

class Sound {
  constructor(path, type, callback) {
    ...
  }

  LIBRARY = 1
}

export Sound;

然后在你的测试中

jest.mock('react-native-sound');

我不完全确定在 react-native 中替换模块的语法(只需确保您的 mocks 文件夹与您所包含的文件夹位于同一目录中),因此您可能还需要指定您正在尝试像这样替换 moduleNameMapper 中的模块,然后我认为您不需要在文件中模拟它。但是,这仅在您计划在全球范围内模拟 react-native-sound 时才有效。

"moduleNameMapper": {
  "react-native-sound": "<rootDir>/__mocks__/react-native-sound.js"
}

现在,如果您对未定义的内容有任何问题,您可以将其添加到您的模拟类中,它会解决问题。

请注意,如果您愿意,也可以使用 es5 语法来执行此操作。

【讨论】:

  • 您好,感谢您的回答。可悲的是它不起作用,基本上我无法模拟该模块。当我尝试从真实类中导入模块时,导入的模块是原来的。
  • 应该是jest.mock('react-native-sound'); - 注意缺少的./.js。您不是在模拟 js 文件,而是在模拟 Node 模块。它应该放在项目根目录下与node_modules 相邻的 __mocks__ 文件夹中。见facebook.github.io/jest/docs/en/manual-mocks.html
  • 很好,我会在答案中更改它。
【解决方案2】:

嗯,我终于找到了问题。

我尝试制作模拟的方式是问题所在,所以我所做的是返回一个新函数来模拟我需要模拟的内容:

jest.mock('react-native-sound', () => {
  var _filename = null;
  var _basePath = null;

  var SoundMocked = (filename, basePath, onError, options) => {
    _filename = filename;
    _basePath = basePath;
    onError();
  }

  SoundMocked.prototype.filename = () => _filename;
  SoundMocked.prototype.basePath = () => _basePath;
  SoundMocked.prototype.play = function (onEnd) { };
  SoundMocked.prototype.pause = function (callback) { };
  SoundMocked.prototype.stop = function (callback) { };
  SoundMocked.prototype.reset = function () { };
  SoundMocked.prototype.release = function () { };
  SoundMocked.prototype.getDuration = function () { };

  SoundMocked.LIBRARY = 2;

  return SoundMocked;
});

【讨论】:

  • 您是否最终不得不在测试模块本身中进行模拟而不是使用__mocks__?我很想看看如何使用 __mocks__ 模拟这样的内置模块,我自己从来没有做过。
  • 嗯,我试过了,但我无法使用自动模拟成功。
猜你喜欢
  • 2018-08-29
  • 2017-06-08
  • 1970-01-01
  • 1970-01-01
  • 2019-11-02
  • 2019-10-08
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多