【问题标题】:Validate React Native Component with Asynchronous Work使用异步工作验证 React Native 组件
【发布时间】:2018-01-07 21:07:26
【问题描述】:

我有一个基本组件,它在 componentDidMount 阶段调用 web 服务并覆盖我状态下的 contents 值:

import React, {Component} from 'react';
import {Text} from "react-native";

class Widget extends Component {

    constructor() {
        super();
        this.state = {
            contents: 'Loading...'
        }
    }

    async componentDidMount() {
        this.setState(...this.state, {
            contents: await this.getSomeContent()
        });
    }

    render() {
        return (
            <Text>{this.state.contents}</Text>
        )
    }

    async getSomeContent() {
        try {
            return await (await fetch("http://someurl.com")).text()
        } catch (error) {
            return "There was an error";
        }
    }
}

export default Widget;

我想使用 Jest 快照在以下每种情况下捕获我的组件的状态:

  • 加载中
  • 成功
  • 错误

问题是我必须引入片状暂停来验证组件的状态。

例如,要查看成功状态,必须在渲染组件后稍作停顿,让 setState 方法有机会赶上:

test('loading state', async () => {

    fetchMock.get('*', 'Some Content');
    let widget = renderer.create(<Widget />);

    // --- Pause Here ---
    await new Promise(resolve => setTimeout(resolve, 100));

    expect(widget.toJSON()).toMatchSnapshot();
});

我正在寻找克服测试用例中异步性的最佳方法,以便正确验证每个状态的快照。

【问题讨论】:

    标签: react-native jestjs


    【解决方案1】:

    如果将异步调用移出setState,则可以延迟setState,直到网络调用解决。然后您可以使用setState's 可选回调(在状态更改后触发)来捕获状态。

    所以,是这样的:

    async componentDidMount() {
     var result = await this.getSomeContent()
     this.setState(...this.state, {
         contents: result
     },
     // setState callback- fires when state changes are complete.
     ()=>expect(this.toJSON()).toMatchSnapshot()
     );
    }
    

    更新:

    如果你想在组件之外指定验证,你可以创建一个 prop,比如 stateValidation 来传递一个验证函数:

    jest('loading state', async () => {
    
        fetchMock.get('*', 'Some Content');
    
        jestValidation = () => expect(widget.toJSON()).toMatchSnapshot();
    
        let widget = renderer.create(<Widget stateValidaton={jestValidation}/>); 
    
    });
    

    然后在组件中使用prop:

    async componentDidMount() {
     var result = await this.getSomeContent()
     this.setState(...this.state, {
         contents: result
     },
     // setState callback- fires when state changes are complete.
     this.props.stateValidaton
     );
    }
    

    【讨论】:

    • 此解决方案会将 Jest 验证放入实现中,而这在应用程序中是不需要的。
    • 如何将它作为道具传递给组件?请参阅上面的“更新”部分。
    • 我仍然相信这会使测试和组件过于紧密耦合。实际上,我最终通过使用 Redux 来分离关注点并让组件简单地使用给定状态来解决这个问题。我认为这最终会变得更干净。
    猜你喜欢
    • 2018-02-20
    • 2019-10-30
    • 2018-06-10
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多