在Babel 7和React-Native 0.56中jest.mock()不是模拟模块

时间:2018-08-30 18:24:04

标签: react-native babeljs jestjs babel-jest

与其他许多人一样,我正在尝试将RN应用程序升级到React-Native 0.56,而Babel使得一切变得如此简单! (这里不是讽刺意味)我可以更新RN,将React更新到最新版本,并使我的应用程序可以编译和运行,但是测试(笑话)不再起作用。

但不是所有测试。我设法解决了几乎所有不同类型的问题,期待这个问题:

meeting actions › creates CLEAR_CURRENT_ATTACHMENTS when clearning current attachments

TypeError: eventActions.refreshEvents.mockImplementation is not a function

  90 |
  91 |   beforeEach(() => {
> 92 |     eventActions.refreshEvents.mockImplementation(() => ({ type: DUMMY_TYPE }));
     |                                ^
  93 |     MockDate.set(A_DATE);
  94 |     store = mockStore({
  95 |       authentication: {

  at Object.<anonymous> (src/calendar/actions/__tests__/meetingActions-test.js:92:32)

测试失败的测试文件(删除所有其他测试以简化示例)

import moment from 'moment';
import MockDate from 'mockdate';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import getToken from 'authentication/selectors/tokenSelector';
import * as actions from '../meetingActions';
import * as eventActions from '../eventActions';
import { getPlannerComments } from '../../selectors/scheduleModificationSelectors';

const {
  CLEAR_CURRENT_ATTACHMENTS,
} = actions;

jest.mock('../eventActions.js');
jest.mock('../../../authentication/selectors/tokenSelector');
jest.mock('../../selectors/scheduleModificationSelectors');

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

describe('meeting actions', () => {
  const A_TOKEN = 'token12345';
  const AN_ID = 'h1234';
  const A_DATE = moment('2016-08-22T21:00:00.000Z');
  const AN_MEETING_EVENT = {
    start: A_DATE,
    end: A_DATE,
    guests: [],
    newGuests: [],
    newAttachments: [],
    contactsToAddToGuestList: [],
    groupsToAddToGuestList: [],
    listsToAddToGuestList: [],
  };
  const AN_ACCOUNT = { id: AN_ID };
  const DUMMY_TYPE = 'Dummy type';
  const PLANNER_COMMENTS = {};
  let store;

  beforeEach(() => {
    eventActions.refreshEvents.mockImplementation(() => ({ type: DUMMY_TYPE }));
    MockDate.set(A_DATE);
    store = mockStore({
      authentication: {
        token: A_TOKEN,
      },
      session: {
        account: AN_ACCOUNT,
      },
      meeting: AN_MEETING_EVENT,
      event: {
        attendees: [],
      },
    });
    getToken.mockImplementation(() => A_TOKEN);
    getPlannerComments.mockImplementation(() => PLANNER_COMMENTS);
  });

  it('creates CLEAR_CURRENT_ATTACHMENTS when clearing current info', () =>
    store.dispatch(actions.clearCurrentInfo())
      .then(() => {
        expect(store.getActions()).toContainEqual({ type: CLEAR_CURRENT_ATTACHMENTS });
      }));

  afterEach(() => {
    MockDate.reset();
  });
});

我有800多个测试因此错误而失败。根据我对问题的了解,它来自jest.mock

jest.mock('../domain/Attachment') // For example

并不是在嘲笑类。因此,附件看起来像普通班级。因此,函数的mockImplementation导致undefined is not a function

{ [Function: Record]
  iconOf: [Function: iconOf],
  iconColorOf: [Function: iconColorOf],
  getCleanName: [Function: getCleanName],
  open: [Function: _callee2],
  parse: [Function: parse] }

Package.json

{
  "name": "MY APP",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest",
    "ios": "react-native run-ios",
    "android": "react-native run-android",
    "test:watch": "npm run test -- --watch",
    "lint": "eslint src --max-warnings=0",
    "install-dep": "npm install && cd ios && pod install"
  },
  "rnpm": {
    "assets": [
      "./src/main/themes/fonts/assets"
    ]
  },
  "jest": {
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
    },
    "preset": "react-native",
    "collectCoverage": true,
    "setupTestFrameworkScriptFile": "<rootDir>/setup-jasmine-env.js",
    "moduleFileExtensions": [
      "js",
      "json",
      "es6",
      "ios.js",
      "android.js"
    ],
    "setupFiles": [
      "./testenv.js"
    ],
    "transformIgnorePatterns": [
      "node_modules/?!(react-native)"
    ]
  },
  "dependencies": {
    "bluebird": "^3.4.6",
    "buffer": "^5.0.0",
    "color": "^2.0.0",
    "deepmerge": "^1.5.2",
    "diacritics": "^1.2.3",
    "immutable": "^3.8.2",
    "linkify-it": "^2.0.3",
    "lodash.debounce": "^4.0.8",
    "moment": "^2.17.0",
    "prop-types": "^15.6.0",
    "react": "16.4.1",
    "react-native": "0.56.0",
    [...] // Lots of dependencies not related to the problem
    "react-navigation": "1.5.11",
    "react-redux": "^5.0.7",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0",
    "reselect": "^3.0.1",
    "socket.io-client": "2.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "babel-core": "^6.26.3",
    "babel-eslint": "7.2.3",
    "babel-jest": "^23.4.2",
    "babel-plugin-module-resolver": "^3.1.1",
    "babel-preset-react-native": "5.0.2",
    "eslint": "^3.11.1",
    "eslint-config-airbnb": "^13.0.0",
    "eslint-import-resolver-babel-module": "5.0.0-beta.0",
    "eslint-plugin-import": "^2.12.0",
    "eslint-plugin-jsx-a11y": "^2.2.3",
    "eslint-plugin-react": "^6.7.1",
    "eslint-plugin-react-native": "^2.2.0",
    "fetch-mock": "^5.1.2",
    "istanbul": "0.4.5",
    "jasmine-reporters": "^2.2.0",
    "jest": "^23.5.0",
    "jest-cli": "23.5.0",
    "mockdate": "^2.0.1",
    "moment-timezone": "^0.5.20",
    "react-dom": "16.4.2",
    "react-test-renderer": "16.4.2",
    "redux-mock-store": "1.3.0",
    "regenerator-runtime": "^0.12.1",
    "remote-redux-devtools": "^0.5.7"
  }
}

请注意,就像Jest,Babel和React-Native GitHub中的多个问题一样,我也有Transform。

"transform": {
   "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},

.babelrc

{
  "presets": ["react-native"],
  "plugins": [
    [
      "module-resolver",
      {
        "root": ["./src"],
        "extensions": [".js", ".ios.js", ".android.js"]
      }
    ]
  ]
}

有人知道吗?

1 个答案:

答案 0 :(得分:2)

如果查看示例here,您会看到mockImplementation仅可以在jest.fn()对象上调用。对于您的情况,您需要先模拟refreshEvents,然后在该模拟上调用mockImplementation

...
eventActions.refreshEvents = jest.fn();
eventActions.refreshEvents.mockImplementation(() => ({ type: DUMMY_TYPE }));
...

如果您想保持已发布的代码不变,则必须在模拟模块附近创建一个子目录__mock__,并在该模块中创建一个模拟该模块中功能的文件子目录,如here所述。

更新:

jest.mock调用会通过babel-jest转换器自动提升到文件的顶部,这正是您所需要的。请注意,您已经在使用开玩笑的变压器。来自docs

  

如果您正在使用babel-jest转换器,并希望使用其他代码预处理器,请记住,以任何方式覆盖“ transform”时,babel-jest都不会自动加载。如果要使用它来编译JavaScript代码,则必须对其进行明确定义。

这意味着您必须在babel-jest的jest配置中显式包括package.json转换。那应该可以解决问题。