0

典型的在线购物商店。我正在尝试测试当用户尝试下订单时 AJAX 请求失败的场景。用户也可以选择订阅服务,但只有在下单成功的情况下才会发出订阅请求。

为了测试这个失败的场景,我使用了 Promise 拒绝,但未捕获的错误冒泡并导致测试失败。

有谁知道我如何测试这个,最好不要在组件的方法中添加catch链接?Jestreact-testing-library是否提供替代方法来测试这种情况?onSubmitConfirmationwait

我知道 Jest 提供.rejects但我无法弄清楚我应该如何重组我的测试以使其与 .rejects 一起使用wait

组件:

class Confirmation extends React.Component {
  onSubmit() {
    const { createOrder, items, subscribeUser, userId } = this.props;
    createOrder({ items })
      .then(() => subscribeUser(userId));
      // no catch here because I use an error boundary component 
      // at the the top level of the App's component tree 
      // to catch and log all errors to a logging service
  }
  
  render() {
    return (
      <div>
        <input 
          type="submit" 
          onClick={this.onSubmit} 
          value="Confirm Order"
        />
      </div>
    )
  }
}

考试:

import React from 'react'
import {
  render,
  fireEvent,
  wait
} from 'react-testing-library'

import Confirmation from './Confirmation'

describe('Confirmation', () => {

  it("should not subscribe when the user's order creation fails", () => {
    const props = {
      userId: 12345,
      items: [{
        id: 121,
        qty: 1
      }, {
        id: 122,
        qty: 2
      }],
      createOrder: jest.fn(() => Promise.reject("Order creation failure")),
      subscribeUser: jest.fn(() => {})
    };

    const {
      container
    } = render( 
      <Confirmation { ...props } />
    );

    fireEvent.click(container.querySelector("#confirm-order"));

    return wait(() => {
      expect(props.createOrder).toHaveBeenCalledWith({
        items: props.items
      });
      expect(props.subscribeUser).not.toHaveBeenCalled();
    });
  });

});

请注意,上面的代码片段是不可执行的——实际上,该组件比上面的示例要复杂一些,但我已尝试在不歪曲问题的情况下尽可能地简化它。

编辑

用错误边界包装<Confirmation/>另一个组件似乎也不起作用。该错误仍然会使组件树冒泡以使测试失败:

开玩笑失败

4

1 回答 1

0

我会创建一个小组件来捕获错误并渲染它:

const onError = jest.fn()
class Catcher extends React.Component {
  componentDidCatch(error, info) {
    onError(error, info)
  }

  render() {
    return this.props.children
  }
}

const { container } = render(
  <Catcher>
    <Confirmation { ...props } />
  </Catcher>
);

// After
expect(onError).toHaveBeenCalledTimes(1)
于 2019-01-18T10:39:48.420 回答