简体   繁体   English

你如何测试 React 组件中的基本方法?

[英]How do you test a basic method in a React Component?

I have a React component that has a simple input form and button to input an email.我有一个 React 组件,它有一个简单的输入表单和按钮来输入电子邮件。 My codebase is unit tested with Jest (using jest-dom and also @testing-library/react) as well as integration tested with Cypress.我的代码库使用 Jest 进行了单元测试(使用 jest-dom 和 @testing-library/react)以及使用 Cypress 进行了集成测试。

I want to write a unit test for this simple method on a React Component called ContactBox.我想在一个名为 ContactBox 的 React 组件上为这个简单的方法编写一个单元测试。

You will note that this handler is simply attached to the form element using onSubmit={this.addEmail}您会注意到这个处理程序只是使用onSubmit={this.addEmail}附加到表单元素

addEmail(event) {
    event.stopPropagation()
    event.preventDefault()
    let email = this.emailCaptureRef.current.value

    let  domain = 'https://somedomain.com/'

    fetch(domain + 'newsletter/sign_up', {
      method: "POST",
      body: JSON.stringify({_method: 'POST', email: email})
    })
      .then((response) => {
        if (response.status >= 400) {

        }
        return response.json().then((result) => {
          this.setState({email_box_used: true})
        })
      })
  }

Is there a good way to go about testing this with Jest ?有没有什么好方法可以用 Jest 测试这个?

I guess what I'm curious about is that the Jest documentation all shows various strategies to render the React component(s), is it possible to unit test this method on the component without having to render?我想我很好奇的是 Jest 文档都显示了渲染 React 组件的各种策略,是否可以在组件上对该方法进行单元测试而不必渲染?

React Component class is just JavaScript class, we can test the methods of the class directly using Class.prototype.method without using React related test utils. React Component 类只是 JavaScript 类,我们可以直接使用Class.prototype.method测试类的方法,无需使用 React 相关的测试工具。

index.tsx : index.tsx

import React, { Component } from 'react';

class ContactBox extends Component {
  emailCaptureRef;
  constructor(props) {
    super(props);
    this.state = { email_box_used: false };
  }

  addEmail(event) {
    event.stopPropagation();
    event.preventDefault();
    const email = this.emailCaptureRef.current.value;
    const domain = 'https://somedomain.com/';

    fetch(domain + 'newsletter/sign_up', {
      method: 'POST',
      body: JSON.stringify({ _method: 'POST', email }),
    }).then((response) => {
      return response.json().then((result) => {
        this.setState({ email_box_used: true });
      });
    });
  }
  render() {
    return (
      <div>
        <form onSubmit={this.addEmail}></form>
      </div>
    );
  }
}

export default ContactBox;

index.test.tsx : index.test.tsx

import ContactBox from './';

const whenStable = () => new Promise((resolve) => setTimeout(resolve));

describe('60403489', () => {
  it('should add email', async () => {
    const mResponse = { json: jest.fn().mockResolvedValueOnce({}) };
    const mFetch = jest.fn().mockResolvedValueOnce(mResponse);
    (global as any).fetch = mFetch;
    const setStateSpy = jest.spyOn(ContactBox.prototype, 'setState').mockReturnValueOnce();
    const mEvent = { stopPropagation: jest.fn(), preventDefault: jest.fn() };
    ContactBox.prototype.emailCaptureRef = { current: { value: 'example@gmail.com' } };
    ContactBox.prototype.addEmail(mEvent);
    await whenStable();
    expect(mFetch).toBeCalledWith('https://somedomain.com/newsletter/sign_up', {
      method: 'POST',
      body: JSON.stringify({ _method: 'POST', email: 'example@gmail.com' }),
    });
    expect(mResponse.json).toBeCalledTimes(1);
    expect(setStateSpy).toBeCalledWith({ email_box_used: true });
  });
});

unit test results with coverage report:带有覆盖率报告的单元测试结果:

 PASS  stackoverflow/60403489/index.test.tsx
  60403489
    ✓ should add email (8ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   83.33 |        0 |   66.67 |   81.25 |                   
 index.tsx |   83.33 |        0 |   66.67 |   81.25 | 6,7,26            
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.822s, estimated 10s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60403489源代码: https : //github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60403489

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM