React-native开玩笑测试失败:TypeError:无法读取未定义的属性“ default”

时间:2019-01-06 22:11:02

标签: react-native jestjs

我有以下代码要编写快照测试。

import React from 'react';
import { AsyncStorage, View, Button, Text, StyleSheet } from 'react-native';
import t from 'tcomb-form-native';

const Login = t.struct({
    email: t.String,
    password: t.String,
});
const Form = t.form.Form;
class SignInScreen extends React.Component {


    render() {
        return (
            <View style={styles.container}>
                <Form ref={c => this._form = c} type={Login}/>
                <Button title="Submit" onPress={this.handleSubmit}/>
                <Button title="Sign Up" onPress={this.handleSignUp}/>
            </View>
        );
    }
}

export default SignInScreen;

const styles = StyleSheet.create({
    container: {
        justifyContent: 'center',
        marginTop: 15,
        padding: 20,
        backgroundColor: '#ffffff',
    }
});

我在命令行中运行jest,在我定义onPress()方法之前,它可以很好地通过测试。

validateCredentials = (email, password) => {
    return true;
};

handleSubmit = async () => {
    const value = this._form.getValue();
    if(value != null) {
        /*
            TODO: Make a query to backend to validate credentials
         */
        if (this.validateCredentials(value['email'], value['password'])) {
            await AsyncStorage.setItem('userToken', 'abc');
            this.props.navigation.navigate('App');
        } else {
            alert('Invalid email or password');
        }
    }
}

handleSignUp =  () => {
    this.props.navigation.navigate('SignUp');
}

然后失败,并显示我不太了解的错误消息。

 FAIL  __tests__/SignInScreen-test.js
  ✕ SignInScreen snapshot test (24ms)

  ● SignInScreen snapshot test

TypeError: Cannot read property 'default' of undefined

   9 | });
  10 | const Form = t.form.Form;
> 11 | class SignInScreen extends React.Component {
     |                                                                                                         ^
  12 | 
  13 | 
  14 |     render() {

  at new SignInScreen (screens/SignInScreen.js:11:423)
  at constructClassInstance (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4810:22)
  at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6581:9)
  at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7408:20)
  at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10149:16)
  at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10181:28)
  at renderRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10267:11)
  at performWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11135:11)
  at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11047:11)
  at performSyncWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11021:7)

  console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8075
    The above error occurred in the <SignInScreen> component:
        in SignInScreen (at SignInScreen-test.js:7)

有趣的配置:

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

.babelrc

{
  "presets": ["module:metro-react-native-babel-preset"]
}

我的测试代码:

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

test('SignInScreen snapshot test', () => {
    const snap = renderer.create(<SignInScreen/>).toJSON();
    expect(snap).toMatchSnapshot();
    });

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

通常,此错误与jest找不到特定模块的mock有关。您需要模拟tcomb,因为它呈现了在您的 SignInClass 中调用的<Form/>组件,您可以这样做:

jest.mock('tcomb-form-native', () => {
  const React = require('React')
  const t = require.requireActual('tcomb-form-native')
  // Patch the base Component class to make rendering possible.
  t.form.Component.prototype.render = function render () {
    return React.createElement(this.getTemplate().name, this.props)
  }
  return t
})