开玩笑嘲笑另一个模块后突然被打破

时间:2018-10-31 09:13:50

标签: typescript unit-testing react-native jestjs react-native-camera

我正在用TypeScript构建一个React Native应用程序。我在单元测试中使用Jest和Enzyme。

我最近使用this package将QRCode Scanner添加到了我的应用中。它取决于this camera package。添加软件包后,我为使用该扫描仪的新组件编写完测试(我们执行TDD)后,我突然注意到某些测试失败:

● Test suite failed to run

    TypeError: Cannot read property 'Aspect' of undefined

      at Object.<anonymous> (node_modules/react-native-camera/src/Camera.js:386:113)
      at Object.<anonymous> (node_modules/react-native-camera/src/index.js:1:413)
      at Object.<anonymous> (node_modules/react-native-qrcode-scanner/index.js:19:26)

与往常一样,我在错误中进行了搜索,并找到了两个修复程序。

  1. 在每次测试中模拟会引发此错误的相机,如下所示:

    jest.mock("react-native-camera", () => "Camera");
    
  2. 像这样在项目级别__mocks__/文件夹中模拟摄像头模块:

    const Camera = {}
    export default Camera;
    

当我这样做时,有关“方面”的错误就消失了。但是现在,Jest开始在涉及节点模块的所有测试中抱怨import

● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/my/folders/node_modules/react-navigation-stack/dist/navigators/createContainedStackNavigator.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { createNavigationContainer } from 'react-navigation';
                                                                                             ^^^^^^

    SyntaxError: Unexpected token import

       9 | import ScannerScreen from "../screens/Scanner";
      10 |
    > 11 | const HomeStack = createStackNavigator({ HomeScreen });
         |                   ^
      12 | const ScannerStack = createStackNavigator({ ScannerScreen });
      13 |
      14 | const MainDrawer = createDrawerNavigator({ HomeStack, ScannerStack });

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
      at Object.get createStackNavigator [as createStackNavigator] (node_modules/react-navigation-stack/dist/index.js:8:12)
      at Object.get createStackNavigator [as createStackNavigator] (node_modules/react-navigation/src/react-navigation.js:29:45)
      at Object.<anonymous> (app/navigation/Navigator.ts:11:19)

第一个奇怪的事情是 这以前没有发生过!的意思是,在我添加此模拟程序和带有其依赖项的QR Code Scanner程序包之前(本机-相机),所有测试均正常!对于Jest来说,转换导入不是问题。

好的,所以我再次搜索了一下,发现有些人可以使用"transform-ignore-patterns"来解决此问题。

这是我尝试过的配置:

transformIgnorePatterns: [
  "<rootDir>/node_modules/react-native/.+"
]

"transformIgnorePatterns": [
  "node_modules/(?!react-native|react-navigation)/"
],

这两个都不起作用。他们导致测试开始之前需要20秒钟(当我只测试一个组件时)或几分钟(当我使用npm test同时运行所有测试时)之间的时间。然后他们将立即失败:

 FAIL  app/components/LoginForm/LoginForm.test.tsx
  ● Test suite failed to run

    The component for route 'LoginScreen' must be a React component. For example:

    import MyScreen from './MyScreen';
    ...
    LoginScreen: MyScreen,
    }

    You can also use a navigator:

    import MyNavigator from './MyNavigator';
    ...
    LoginScreen: MyNavigator,
    }

      14 | const MainDrawer = createDrawerNavigator({ HomeStack, ScannerStack });
      15 |
    > 16 | const RootSwitch = createSwitchNavigator(
         |                    ^
      17 |   { MainDrawer, LoadingScreen, LoginScreen },
      18 |   { initialRouteName: "LoadingScreen" }
      19 | );

      at node_modules/react-navigation/src/routers/validateRouteConfigMap.js:24:13
          at Array.forEach (<anonymous>)
      at validateRouteConfigMap (node_modules/react-navigation/src/routers/validateRouteConfigMap.js:14:14)
      at _default (node_modules/react-navigation/src/routers/SwitchRouter.js:22:39)
      at createSwitchNavigator (node_modules/react-navigation/src/navigators/createSwitchNavigator.js:7:42)
      at Object.SwitchNavigator (node_modules/react-navigation/src/navigators/createContainedSwitchNavigator.js:5:54)
      at Object.<anonymous> (app/navigation/Navigator.ts:16:20)

这是怎么回事?为什么Jest突然坏了?在react-native-camera出现之前,导入工作正常。

添加的信息:

这是我的配置文件。

package.json

"jest": {
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
    "^.+\\.tsx?$": "ts-jest"
  },
  "globals": {
    "ts-jest": {
      "tsConfigFile": "tsconfig.jest.json"
    }
  },
  "transformIgnorePatterns": [
    "node_modules/(?!react-native|react-navigation)/"
  ],
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "json",
    "node"
  ],
  "modulePaths": [
    "<rootDir>"
  ],
  "setupFiles": [
    "./tests/setup.js"
  ]
}

tsconfig.jest.json

{
  "extends": "./tsconfig",
  "compilerOptions": {
    "jsx": "react",
    "module": "commonjs"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "jsx": "react-native",
    "lib": ["es2017"],
    "moduleResolution": "node",
    "noEmit": true,
    "strict": true,
    "strictPropertyInitialization": false,
    "target": "esnext"
  },
  "exclude": ["node_modules"]
}

tests/setup.js

import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import { NativeModules } from "react-native";

jest.mock("react-native-device-info", () => {
  return {
    getDeviceName: jest.fn(() => "device name"),
    getBrand: jest.fn(() => "android"),
    getDeviceId: jest.fn(() => "device-id-123")
  };
});
NativeModules.ReactLocalization = {
  language: "en"
};
global.fetch = require("jest-fetch-mock"); // eslint-disable-line no-undef
Enzyme.configure({ adapter: new Adapter() });

0 个答案:

没有答案