【问题标题】:How to test React ErrorBoundary如何测试 React 错误边界
【发布时间】:2018-08-19 14:40:00
【问题描述】:

React 新手,但不是测试应用程序。

我想确保每次组件抛出错误时都会显示 ErrorBoundary 消息。如果您不知道我所说的 ErrorBoundary 是什么意思,这里是 link

我正在使用Mocha + Chai + Enzyme

假设我们需要使用以下测试配置来测试React counter example

测试配置

// DOM
import jsdom from 'jsdom';
const {JSDOM} = jsdom;
const {document} = (new JSDOM('<!doctype html><html><body></body></html>')).window;
global.document = document;
global.window = document.defaultView;
global.navigator = global.window.navigator;

// Enzyme
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

// Chai
import chai from 'chai';
import chaiEnzyme from 'chai-enzyme';
chai.use(chaiEnzyme());

更新 1 - 后来的一些想法

在阅读this conversation 关于连接组件的最佳测试方法(涉及类似问题)之后,我知道我不必担心componentDidCatch 会发现错误。 React 已经过足够的测试,可以确保无论何时抛出错误都会被捕获。

因此只有测试两个测试:

1:确保 ErrorBoundary 在出现任何错误时显示消息

// error_boundary_test.js
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';

import ErrorBoundary from './some/path/error_boundary';

describe('Error Boundary', ()=>{
    it('generates a error message when an error is caught', ()=>{
        const component = shallow(<ErrorBoundary />);
        component.setState({
            error: 'error name', 
            errorInfo: 'error info'
        });
        expect(component).to.contain.text('Something went wrong.');
    });
});

2:确保组件被包裹在 ErrorBoundary 内(在 React counter example 中是 &lt;App /&gt;,这是一种误导。我们的想法是在最近的父组件上执行此操作)。

注意:1)它需要在父组件上完成,2)我假设子组件是简单的组件,而不是容器,因为它可能需要更多配置。 进一步的想法:这个测试最好用parent而不是descendents写...

// error_boundary_test.js
import React from 'react';
import { expect } from 'chai';
import { shallow } from 'enzyme';

import App from './some/path/app';

describe('App', ()=>{
    it('wraps children in ErrorBoundary', ()=>{
        const component = mount(<App />);
        expect(component).to.have.descendants(ErrorBoundary);
    });

【问题讨论】:

    标签: reactjs unit-testing testing enzyme


    【解决方案1】:

    使用 React 测试库测试 ErrorBoundary 组件

    const Child = () => {
      throw new Error()
    }
    
    describe('Error Boundary', () => {
      it(`should render error boundary component when there is an error`, () => {
        const { getByText } = renderProviders(
          <ErrorBoundary>
            <Child />
          </ErrorBoundary>
        )
        const errorMessage = getByText('something went wrong')
        expect(errorMessage).toBeDefined()
      })
    })
    

    renderProviders

    import { render } from '@testing-library/react'
    
    const renderProviders = (ui: React.ReactElement) => render(ui, {})
    

    【讨论】:

    • 有趣的是,您提到了“hasError 状态”,但您发布的代码实际上都没有使用它。
    【解决方案2】:

    这是我没有设置组件状态的尝试:

    错误边界:

    import React, { Component } from 'react';
    import ErroredContentPresentation from './ErroredContentPresentation';
    
    class ContentPresentationErrorBoundary extends Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
    
      componentDidCatch(error, info) {
        this.setState({ hasError: true });
      }
    
      render() {
        return this.state.hasError ? <ErroredContentPresentation /> : this.props.children;
      }
    }
    
    export const withErrorBoundary = WrappedComponent =>
      props => <ContentPresentationErrorBoundary>
                <WrappedComponent {...props}/>
              </ContentPresentationErrorBoundary>;
    

    还有测试:

    it('Renders ErroredContentPresentation Fallback if error ', ()=>{
      const wrappedComponent = props => {
        throw new Error('Errored!');
      };
      const component = withErrorBoundary( wrappedComponent )(props);
      expect(mount(component).html()).toEqual(shallow(<ErroredContentPresentation/>).html());
    });
    

    【讨论】:

      猜你喜欢
      • 2021-11-30
      • 2020-03-03
      • 2021-08-09
      • 2020-01-16
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多