【问题标题】:Mock specific React hooks in Promises with react-testing-library and ts-jest使用 react-testing-library 和 ts-jest 在 Promises 中模拟特定的 React 钩子
【发布时间】:2020-05-09 18:42:07
【问题描述】:

我正在尝试测试在提交表单后在 Promise 链中触发的 2 个 useState 钩子。

所有附加到元素的钩子(例如电子邮件、提交按钮)都可以正常工作,但它会更新 Promise 链中的状态,我不知道如何访问以进行模拟/测试。

    // submit function in ContactForm.tsx
    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault()
        const data = { firstName, lastName, email, message, subscribe }

        setLoading(true)
        fetchWrapper('/', encode(data))
            .then(() => {
                setStatus(true) // <= throws 'act(() => {...)' error
                props.onSubmit(data) // mock function passed in to check data submitted matches
            })
            .catch(error => {
                setStatus(false) // <= throws 'act(() => {...)' error
            })
            .finally(() => setLoading(false))
    }
    // ContactForm.spec.tsx
    import React from 'react'
    import { mocked } from 'ts-jest/utils'
    import { render, fireEvent } from '@testing-library/react'
    import ContactForm, { ContactFormProps } from './ContactForm'
    import { fetchWrapper } from '../../../utils/fetchWrapper'

    jest.mock('../../../utils/fetchWrapper')

    let mockedFetch

    beforeEach(() => {
        jest.clearAllMocks()
        mockedFetch = mocked(fetchWrapper)
    })

    it('should submit with firstName, lastName, email, message and subscribe', () => {
        // ASSEMBLE
        const onSubmit = jest.fn()

        const utils = renderContactForm({
            subscribe: false,
            onSubmit,
        })

        const firstName = utils.getByTestId('firstName')
        const lastName = utils.getByTestId('lastName')
        const email = utils.getByTestId('email')
        const message = utils.getByTestId('message')
        const subscribe = utils.getByTestId('subscribe')
        const submit = utils.getByTestId('SEND MESSAGE')

        mockedFetch.mockImplementationOnce(() => Promise.resolve())

        // ACT
        fireEvent.change(firstName, { target: { value: 'Clark' } })
        fireEvent.change(lastName, { target: { value: 'Kent' } })
        fireEvent.change(email, { target: { value: 'lastson@krypton.com' } })
        fireEvent.change(message, { target: { value: 'I like the sun' } })
        fireEvent.click(subscribe)
        fireEvent.click(submit)

        // ASSERT
        expect(onSubmit).toHaveBeenCalledWith({
            firstName: 'Clark',
            lastName: 'Kent',
            email: 'lastson@krypton.com',
            message: 'I like the sun',
            subscribe: true,
        })
    })

我看到的错误是:

    Warning: An update to ContactForm inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
        /* fire events that update state */
    });
    /* assert on the output */

    This ensures that you're testing the behavior the user would see in the browser

文档似乎不是特别有用,因为它们使用了一个简单的示例,而不是测试副作用

注意:如果可能,我宁愿避免使用酶

提前致谢

【问题讨论】:

    标签: jestjs react-hooks ts-jest


    【解决方案1】:

    答案是将 fireEvent.click(submit) 包装在来自 'react-dom/test-utils` 的 act()

    it('should submit with firstName, lastName, email, message and subscribe', async () => {
        // ASSEMBLE
        const onSubmit = jest.fn()
        const handleCallback = jest.fn()
    
        const utils = renderContactForm({
            subscribe: false,
            onSubmit,
            handleCallback,
        })
    
        const firstName = utils.getByTestId('firstName')
        const lastName = utils.getByTestId('lastName')
        const email = utils.getByTestId('email')
        const message = utils.getByTestId('message')
        const subscribe = utils.getByTestId('subscribe')
        const submit = utils.getByTestId('SEND MESSAGE')
    
        mockedFetch.mockImplementationOnce(() => Promise.resolve())
    
        // ACT
        fireEvent.change(firstName, { target: { value: 'Clark' } })
        fireEvent.change(lastName, { target: { value: 'Kent' } })
        fireEvent.change(email, {
            target: { value: 'lastson@krypton.com' },
        })
        fireEvent.change(message, { target: { value: 'I like the sun' } })
        fireEvent.click(subscribe)
    
        await act(async () => { // the await / async here is important
            fireEvent.click(submit)
        })
    
        // ASSERT
        expect(onSubmit).toHaveBeenCalledWith({
            firstName: 'Clark',
            lastName: 'Kent',
            email: 'lastson@krypton.com',
            message: 'I like the sun',
            subscribe: true,
        })
    })
    

    【讨论】:

      猜你喜欢
      • 2021-10-10
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 2021-01-13
      • 2019-10-30
      • 2021-02-11
      • 2023-03-13
      相关资源
      最近更新 更多