Jest + Enzyme + React TypeError:TypeError:无法读取未定义的属性“length”

时间:2018-02-13 16:42:12

标签: reactjs typescript enzyme jest

您好我正在尝试为我的一个反应组件编写单元测试,并且我一直收到同样的错误TypeError: Cannot read property 'length' of undefined。我有87个通过测试和8个通过测试套件,所以我不明白这个特定的测试/组件有什么问题。我正在使用Jest + Enzyme + React + Typescript。我尝试过使用酶RenderShallowMount方法,但我仍然遇到同样的错误。

这是我的反应部分:

import * as React from 'react';
import { 
    Button,
    ButtonStyle,
    Tabs, 
    Tab, 
    StatusType
} from 'oui-react';
import { Dispatch } from 'redux';
import { HeaderComponent } from '../../main/';
import ManageSettingsComponent  from './ManageSettings/ManageSettingsComponent'
import { 
    updateEndpoint
} from '../../Endpoints';

interface DetailViewComponentProps {
    singleEndpoint: any;
    dispatch: Dispatch<{}>;
    updateEndpoint: (endpoint:any) => void;
}

const breadcrumbItems= [
    { label: "Networking", href: "#/a/networking/vcns" }, 
    { label: "CDN", href: "/#/cdn"},
    { label: "Detail View"}
];

const buttonItems= [
    { title: "Apply Tags", class:"", buttonStyle: ButtonStyle.Default },
    { title: "SSL Request", class:"oui-margin-small-left", buttonStyle: ButtonStyle.Default },
    { title: "Activate", class:"oui-margin-small-left", buttonStyle: ButtonStyle.Default },
    { title: "Purge", class:"oui-margin-small-left", buttonStyle: ButtonStyle.Default },
    { title: "Delete", class: "oui-margin-small-left", buttonStyle: ButtonStyle.Danger}
];

const buttons = buttonItems.map( (buttonItem, i) => 
    <span className={buttonItem.class} key={i}>
        <Button
            buttonStyle={buttonItem.buttonStyle} 
        >
            {buttonItem.title}
        </Button>
    </span>
);

export class DetailViewComponent extends React.Component<DetailViewComponentProps, any> { 
    constructor(props: any) {
        super(props);

        this.state = {
            disabledButtons: true

        };
        this.changeEndpointState = this.changeEndpointState.bind(this);
        this.handleCancel = this.handleCancel.bind(this);
    }

    componentWillMount(){
        const { 
            id, 
            label, 
            hostname,
            origin,
            originType, 
            originValidation, 
            ocid, 
            lastModified, 
            status, description 
        } = this.props.singleEndpoint;

        if (this.props.singleEndpoint) {
            this.setState({ 
                id: id, 
                label: label,
                hostname: hostname, 
                origin: origin,
                originType: originType, 
                originValidation: originValidation,
                ocid: ocid,
                lastModified: lastModified,
                status: status,
                description: description
            })
        }
    }

    changeEndpointState(e: any) {
        const target = e.target;
        const value = target.value;
        const name = target.name;

        this.setState({[name]: value, disabledButtons: false});
    }

    handleCancel(e:any){
        const { 
            id, 
            label, 
            hostname, 
            originType, 
            origin,
            originValidation, 
            ocid, 
            lastModified, 
            status, 
            description 
        } = this.props.singleEndpoint;

        this.setState({
            id: id, 
            label: label,
            hostname: hostname, 
            origin: origin,
            originType: originType, 
            originValidation: originValidation,
            ocid: ocid,
            lastModified: lastModified,
            status: status,
            description: description,
            disabledButtons: true
        })
    }

    handleSubmit(endpoint:any){
        this.setState({
            disabledButtons: true
        })
        console.log(endpoint);
        this.props.updateEndpoint(endpoint);
    }

    render(){
        const { 
            id, 
            label, 
            hostname,
            origin: origin, 
            originType, 
            originValidation, 
            ocid, 
            lastModified, 
            status,
            description,
            disabledButtons 
        } = this.state;  
        const { updateEndpoint } = this.props;

        return( 
            <div>   
                <HeaderComponent 
                    pageTitle={this.props.singleEndpoint.label} 
                    showStatus={true}
                    statusType={status == 'Active' ? StatusType.Success : StatusType.Muted}
                    statusText={status}
                    breadcrumbItems={breadcrumbItems}
                />
                <div className="oui-section oui-section-muted oui-section-xsmall">
                    <div className="oui-container">
                        { buttons }
                    </div>
                </div>
                <div className="oui-margin-medium-top oui-container">
                <Tabs>
                    <Tab label="Manage Settings">
                        <ManageSettingsComponent
                            id={id}
                            label= {label}
                            hostname= {hostname}
                            origin =  {origin}
                            originType={originType}
                            originValidation={originValidation}
                            ocid= {ocid}
                            lastModified= {lastModified}
                            status= {status}
                            description= {description} 
                            disabledButtons = {disabledButtons}
                            handleChange={this.changeEndpointState}
                            handleCancel={this.handleCancel}
                            handleSubmit={(endpoint:any) => this.handleSubmit(endpoint)}
                            />
                    </Tab>
                    <Tab label="Reports" />
                    <Tab label="Tags" />
                </Tabs>

                </div>
            </div>
        );
    }
};

export default DetailViewComponent;

这是我的测试文件:

import * as React from 'react';
import DetailViewComponent from '../components/DetailViewComponent';
import { HeaderComponent } from '../../main/';
import ManageSettingsComponent  from '../components/ManageSettings/ManageSettingsComponent'
import { shallow } from 'enzyme';
import { Dispatch } from 'redux';
import { 
    Button,
    ButtonStyle,
    Tabs, 
    Tab, 
    StatusType
} from 'oui-react';

describe('<DetailViewComponent />', () => {
    let wrapper: any;
    let componentInstance: any;

    let singleEndpoint: {};
    let dispatch: Dispatch<{}>;
    let updateEndpoint: () => void;

    beforeEach(() => {
        wrapper = shallow(
            <DetailViewComponent
                singleEndpoint={singleEndpoint}
                dispatch={dispatch}
                updateEndpoint={updateEndpoint}
            />
        );
        componentInstance = wrapper.instance();
    });

    it('Renders the component', () => {
        expect(wrapper.length).toEqual(1);
    });

});

1 个答案:

答案 0 :(得分:0)

我认为这是因为您将undefined singleEndpoint的值传递给您的组件,导致componentWillMount()失败。改变这一行:

let singleEndpoint: {};

对此:

let singleEndpoint = {};

最初的测试通过了。