由于async react本机组件,Jest测试失败

7fhtutme  于 2023-09-28  发布在  Jest
关注(0)|答案(1)|浏览(134)

我有一个基本的测试入口App.tsx:

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from './Screens/HomeScreen';
import { StudentProps, RootStackParamList } from './types/StudentInfo';

export default function App(props: StudentProps): React.JSX.Element {
  const Stack = createNativeStackNavigator<RootStackParamList>();
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="ReactNative">
        <Stack.Screen
          name="ReactNative"
          component={HomeScreen}
          initialParams={{ studentList: props }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

这个App.tsx组件以JSON字符串的形式检索props:

Running "RNProject" with {"initialProps":{"studentList":["{\"name\":\"John Doe\",\"course\":\"Jest\"}","{\"name\":\"Jane Doe\",\"course\":\"Reac Native\"}"]},"rootTag":21}

App.test.tsx:

import 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
import App from '../App';

test('renders correctly', () => {
  const tree = renderer
    .create(
      <App
        appList={[
          '{"name":"John Doe","course":"Jest"}',
          '{"name":"Jane Doe","course":"React Native"}'
        ]}
      />
    )
    .toJSON();
  expect(tree).toMatchSnapshot();
});

我在jest.config中的配置:

module.exports = {
  preset: "react-native",
  verbose: true,
  transformIgnorePatterns: [
    "node_modules/(?!(@react-native|react-native|@react-navigation|uuid|react-native-shared-group-preferences)/)",
  ],
};

package.json:

{
  "name": "rnproject",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "lint": "tsc --noEmit && eslint --ext .js,.jsx,.ts,.tsx",
    "lint-and-fix": "tsc --noEmit && eslint --ext .js,.jsx,.ts,.tsx --fix",
    "prettier-format": "prettier --config .prettierrc '**/*.{js,jsx,ts,tsx}' --write",
    "start": "react-native start",
    "postinstall": "npx patch-package",
    "test": "jest"
  },
  "dependencies": {
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/native-stack": "^6.9.13",
    "@react-navigation/stack": "^6.3.17",
    "eslint-plugin-jsx-a11y": "^6.7.1",
    "patch-package": "^8.0.0",
    "react": "18.2.0",
    "react-native": "0.72.4",
    "react-native-get-random-values": "^1.9.0",
    "react-native-launcher-kit": "^1.0.4",
    "react-native-safe-area-context": "^4.7.2",
    "react-native-screens": "^3.25.0",
    "react-native-shared-group-preferences": "^1.1.23",
    "uuid": "^9.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-env": "^7.20.0",
    "@babel/runtime": "^7.20.0",
    "@jest/globals": "^29.7.0",
    "@react-native/metro-config": "^0.72.11",
    "@tsconfig/react-native": "^3.0.0",
    "@types/jest": "^29.5.5",
    "@types/react": "^18.0.24",
    "@types/react-native-shared-group-preferences": "^1.1.1",
    "@types/react-test-renderer": "^18.0.0",
    "@types/uuid": "^9.0.4",
    "@typescript-eslint/eslint-plugin": "^6.7.2",
    "@typescript-eslint/parser": "^6.7.2",
    "babel-jest": "^29.2.1",
    "eslint": "^8.49.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-prettier": "^5.0.0",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "jest": "^29.2.1",
    "jest-cli": "^29.7.0",
    "metro-react-native-babel-preset": "0.76.8",
    "prettier": "^3.0.3",
    "react-test-renderer": "18.2.0",
    "ts-jest": "^29.1.1"
  },
  "engines": {
    "node": ">=16"
  }
}

当运行npm run test时,我得到以下错误:

> [email protected] test
> jest

ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From __tests__/App.test.tsx.
      at Object.get BackHandler [as BackHandler] (node_modules/react-native/index.js:109:12)
      at node_modules/@react-navigation/native/lib/commonjs/useBackButton.js:50:37
      at commitHookEffectListMount (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12999:26)        
      at commitPassiveMountOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14422:11)        
      at commitPassiveMountEffects_complete (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14382:9)      at commitPassiveMountEffects_begin (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14369:7)   
      at commitPassiveMountEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14357:3)
      at flushPassiveEffectsImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16248:3)
      at flushPassiveEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16197:14)
      at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16012:9
      at workLoop (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:266:34)
      at flushWork (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:239:14)
      at Immediate.performWorkUntilDeadline [as _onImmediate] (node_modules/react-test-renderer/node_modules/scheduler/cjs/scheduler.development.js:533:21)
  console.error
    The above error occurred in the <ForwardRef(NavigationContainerInner)> component:
    
        at NavigationContainerInner (C:\Github\bcgov\IAS\ReactNativeProject\node_modules\@react-navigation\native\src\NavigationContainer.tsx:107:23)
        at App
    
    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

      at logCapturedError (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8661:23)

tsx组件接收包含学生作为 prop 的JSON字符串。然后,HomeScreen被调用,它正在调用另一个执行异步函数的组件Students。我怎么能让jest等到App组件的子组件完成呢?

cvxl0en2

cvxl0en21#

通常你可以使用waitfor(推荐)来等待更改:

test('renders correctly', async() => {
  const tree = renderer
    .create(
      <App
        appList={[
          '{"name":"John Doe","course":"Jest"}',
          '{"name":"Jane Doe","course":"React Native"}'
        ]}
      />
    )
    .toJSON();
  await waitFor(() => {
    expect(tree).toMatchSnapshot();
  })
});

或者你可以将触发更改的事件 Package 在中(在这里不起作用,当你按下一个按钮时,这更有效):

await act(async() => {
await //the event
})

另外,我看到你没有使用react-native-testing-library,我强烈建议你使用它。Waitfor包含在该库中,我真的不知道如果没有它,你如何有效地测试RN应用程序:https://callstack.github.io/react-native-testing-library/docs/api

相关问题