繁体   English   中英

ReactJS单元测试-TypeError:this.props.onChange不是一个函数

[英]ReactJS Unit Testing - TypeError: this.props.onChange is not a function

我正在使用涉及登录的karma + jasmine对React Components进行单元测试。 测试总是抛出错误

? LoginForm test > ValidatedInput test > should validate password

TypeError:this.props.onChange不是一个函数

 at ValidatedInput.handleChangeValue (src/components/ValidatedInput.js:14:24)
 at node_modules/enzyme/build/ShallowWrapper.js:844:23
 at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-test-renderer/lib/shallow/Transaction.js:143:20)
 at Object.batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactDefaultBatchingStrategy.js:62:26)
 at Object.batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactUpdates.js:97:27)
 at ReactShallowRenderer.unstable_batchedUpdates (node_modules/react-test-renderer/lib/shallow/ReactShallowRenderer.js:130:25)
 at performBatchedUpdates (node_modules/enzyme/build/ShallowWrapper.js:103:21)
 at node_modules/enzyme/build/ShallowWrapper.js:843:13
 at withSetStateAllowed (node_modules/enzyme/build/Utils.js:284:3)
 at ShallowWrapper.simulate (node_modules/enzyme/build/ShallowWrapper.js:840:42)
 at Object.<anonymous> (src/__tests__/login-test.js:93:37)
 at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
 at process._tickCallback (internal/process/next_tick.js:109:7)

以下是我的文件:

LoginForm.js呈现组件

<ValidatedInput
    name={'userId'}
    type={'text'}
    title={'User ID'}
    value={this.state.userId}
    placeholder={'Enter User ID'}
    onChange={this.handleUserIdChange}
    onComponentMounted={this.handleRegisterFormFields}
    validations={/^[0-9]{5,10}$/}
    validationError={'This is not valid user Id'}
    isRequired={true}
/>

我在构造函数中绑定了handleUserIdChange ,并在类主体中将其定义为

handleUserIdChange(value) {
    this.setState({ userId : value });
}

ValidatedInput.js

import React, { Component } from 'react';

class ValidatedInput extends Component {
    constructor(props) {
        super(props);

        this.handleChangeValue = this.handleChangeValue.bind(this);
        this.isValid = this.isValid.bind(this);
        this.validateInput = this.validateInput.bind(this);
    }

    /**********************************************/
    // referred function //
    handleChangeValue(e) {
        this.props.onChange(e.target.value);
        var isValidField = this.isValid(e.target);
    }
    /**********************************************/    
    isValid(input) {
        if (input.getAttribute('required') !== null && input.value === "") {
            input.classList.add('Error');
            input.nextSibling.textContent = this.props.validationError;
            return false;
        } else {
            input.classList.remove('Error');
            input.nextSibling.textContent =  '';
        }

        if(input.value !== "") {
            if(!this.validateInput(input.value)) {
                input.classList.add('Error');
                input.nextSibling.textContent = this.props.validationError;
                return false;
            } else {
                input.classList.remove('Error');
                input.nextSibling.textContent =  '';
            }
        }
            return true;
    }

    validateInput(value) {
        var regularExpressionToBeMatched = this.props.validations;
        return regularExpressionToBeMatched.test(value);
    }

    componentDidMount() {
        if (this.props.onComponentMounted) {
            this.props.onComponentMounted(this);
        }
    }

    render () {
        console.log(this.props.onChange);
        return (
            <div className="form-group">
                <div className="col-5 text-center">
                    <label htmlFor={this.props.name}>{this.props.title}</label>
                </div>
                <div className="col-5 text-center">
                    <input
                        className="form-input text-center"
                        type={this.props.type}
                        ref={this.props.name}
                        name={this.props.name}
                        value={this.props.value}
                        required={this.props.isRequired}
                        placeholder={this.props.placeholder}
                        onChange={this.handleChangeValue}
                    />
                    <span className='Error'></span>
                </div>
            </div>
        );
    }
}

export default ValidatedInput;

以下是测试代码:

it('should validate userId', () => {
    const component = shallow( <ValidatedInput
            name={'userId'}
            type={'text'}
            title={'User Id'}
            value={'001251623'}
            placeholder={'Enter User Id'}
            validations={/^[0-9]{5,10}$/}
            validationError={'This is not valid user Id'}
            isRequired={true}
    />);
    const handleChangeValue = spyOn(component.instance(), 'handleChangeValue');
    component.find('input').simulate('change', {target: { value: '00125' } });
    // expect(component.state().value).equals("00125");
    expect(handleChangeValue.calledWith('00125'));
});

我在所有资源中进行了广泛研究。 该应用程序运行良好,ValidatedInput中的console.log(this.props.onChange)表示已绑定handleUserIdChange 请提出解决方法或进行更改。 谢谢。

编辑1

LoginForm.js

class LoginForm extends Component {
    constructor(props) {
        super(props);
        this.state = {
            userId : '',
            password : '',
            loginType : ['Customer', 'Payer', 'Super-User'],
            userLoggedInAs : ['Customer'],
            userType : '',
            FieldsRegister : [],
            serverMessage : '',
        }
        this.handleClearForm = this.handleClearForm.bind(this);
        this.handleSubmitForm = this.handleSubmitForm.bind(this);
        this.handleUserIdChange = this.handleUserIdChange.bind(this);
        this.handlePasswordChange = this.handlePasswordChange.bind(this);
        this.handleUserTypeChangeSelect = this.handleUserTypeChangeSelect.bind(this);
        this.handleRegisterFormFields = this.handleRegisterFormFields.bind(this);
    }

    handleUserIdChange(value) {
        this.setState({ userId : value });
    }
...

编辑2

it('should validate userId', () => {
            const component = shallow( <ValidatedInput
                    name={'userId'}
                    type={'text'}
                    title={'User Id'}
                    value={'001251623'}
                    placeholder={'Enter User Id'}
                    validations={/^[0-9]{5,10}$/}
                    validationError={'This is not valid user Id'}
                    isRequired={true}
                    onChange={handleUserIdChange()}
            />);
            const handleChangeValue = spyOn(component.instance(), 'handleChangeValue');
            component.find('input').simulate('change', {target: { value: '00125' } });
            // expect(component.state().value).equals("00125");
            expect(handleChangeValue.calledWith('00125'));
        });

在您的示例中, <ValidateInput>组件具有onChange属性:

<ValidatedInput
    ...
    onChange={this.handleUserIdChange}

但是在您的测试中却没有:

        const component = shallow( <ValidatedInput
                name={'userId'}
                type={'text'}
                title={'User Id'}
                value={'001251623'}
                placeholder={'Enter User Id'}
                validations={/^[0-9]{5,10}$/}
                validationError={'This is not valid user Id'}
                isRequired={true}
                ---> Missing the onChange={..} <---
        />);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM