Jest/Enzyme 使用 try/catch 中的 async/await 方法测试 React 组件

Posted

技术标签:

【中文标题】Jest/Enzyme 使用 try/catch 中的 async/await 方法测试 React 组件【英文标题】:Jest/Enzyme test React component with async/await method in try/catch 【发布时间】:2019-08-12 16:32:17 【问题描述】:

多年来,我一直在努力尝试用 Jest 测试这种方法,在线搜索似乎没有帮助。我想我需要重构这个方法,但我不确定如何以可测试的方式来做。

class EmailPage extends Component 
  ...
  async onSubmit(values, applicaitonId) 
    try 
      this.setState( loading: true );
      const response = await sendEmail(this.formatEmailValues(values), applicaitonId);
      console.log(response)
      this.setState( loading: false );
      if (response.status !== 'error') 
        this.props.history.push('/dashboard');
       else 
        alert(
          `Something was wrong with your email. Error: $response.message`
        );
      
     catch (error) 
      console.error('Error while sending email!');
      console.error(error);
      this.setState( loading: false );
    
  
  ...

有什么想法吗?

【问题讨论】:

您可以模拟 sendEmail 函数并使其在测试期间拒绝并解决 【参考方案1】:

这应该让你开始:

import * as React from 'react';
import  shallow  from 'enzyme';

let sendEmail = () => ;

class EmailPage extends React.Component 

  formatEmailValues()  return 'formatEmailValues return value'; 

  async onSubmit(values, applicaitonId) 
    try 
      this.setState( loading: true );
      const response = await sendEmail(this.formatEmailValues(values), applicaitonId);
      console.log(response)
      this.setState( loading: false );
      if (response.status !== 'error') 
        this.props.history.push('/dashboard');
       else 
        alert(
          `Something was wrong with your email. Error: $response.message`
        );
      
     catch (error) 
      console.error('Error while sending email!');
      console.error(error);
      this.setState( loading: false );
    
  

  render()  return null; 


describe('EmailPage', () => 

  test('onSubmit', async () => 
    const historyMock =  push: jest.fn() ;
    const wrapper = shallow(<EmailPage history=historyMock />);
    const instance = wrapper.instance();

    let sendEmailResolve;
    sendEmail = jest.fn(() => new Promise(resolve =>  sendEmailResolve = resolve; ));
    const formatEmailValuesSpy = jest.spyOn(EmailPage.prototype, 'formatEmailValues');

    const promise = instance.onSubmit(['value1', 'value2'], 'applicationId');
    expect(wrapper.state().loading).toBe(true);  // Success!
    expect(formatEmailValuesSpy).toHaveBeenCalledWith(['value1', 'value2']);  // Success!
    expect(sendEmail).toHaveBeenCalledWith('formatEmailValues return value', 'applicationId');  // Success!

    sendEmailResolve( status: 'success' );  // simulate sendEmail resolving
    await promise;  // let onSubmit finish

    expect(wrapper.state().loading).toBe(false);  // Success!
    expect(historyMock.push).toHaveBeenCalledWith('/dashboard'); // Success!
  )
)

我将把它作为练习留给读者来实现error 案例。

(...但是要开始这项工作,您需要在测试期间模拟 global.alert 并调用 sendEmailResolve( status: 'error' );

【讨论】:

非常感谢,这真的很有帮助。

以上是关于Jest/Enzyme 使用 try/catch 中的 async/await 方法测试 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

React / Enzyme:运行 Jest / Enzyme 测试时出现 Invariant Violation 错误

使用 Jest / Enzyme 在 React 中的功能组件内部测试方法

如何使用 Jest/Enzyme 测试去抖功能?

如何使用 jest/enzyme 测试 useEffect 与 useDispatch 挂钩?

测试:使用 Jest/Enzyme 寻找风格化的情感成分

使用钩子时 Jest/Enzyme 测试抛出错误