【问题标题】:Test component with mock React Jest使用模拟 React Jest 测试组件
【发布时间】:2021-12-10 21:55:11
【问题描述】:

这是我的组件,它包含一个 Select 子组件

import { hashHistory } from 'react-router'
import { useEffect } from 'react'

import Select from 'cm/components/common/select'
import { eventTracker, events } from 'cm/common/event-tracker'
import { eventMetricsMap } from './helpers'
import { compose } from 'cm/common/utils'

const SelectLanguage = ({ handlers, languages, selectedLanguage }) => {
    useEffect(() => {
        hashHistory.listen(({ pathname }) => {
            if (pathname.indexOf('/library')) {
                handlers.onSelect(null)
            }
        })
    }, [])

    const handleSelect = ({ value }) => {
        handlers.onSelect(value)

        return value.toLowerCase()
    }

    const trackSelectLanguage = language => {
        eventTracker.track(
            events.switchBuildingBlickLanguage,
            {
                from: eventMetricsMap[ 'buildingblocks' ][ 'from' ],
                language
            }
        )
    }

    return (
        <Select
            className="search__form--lang dropdown-selection--fixed-width"
            handlers={{
                onSelect: compose(
                    trackSelectLanguage,
                    handleSelect
                )
            }}
            items={languages}
            selected={selectedLanguage}
            type="medium-input"
        />
    )
}

我想使用 Jest 对此组件进行单元测试。我想介绍的 4 个测试用例:

  • 在文档中呈现
  • 渲染项目
  • 轨道选择打开点击
  • 处理操作

很遗憾最后两个案例都失败了,找不到原因。

你知道怎么解决吗?

import expect from 'expect'
import { fireEvent, render } from '@testing-library/react'

import SelectLanguage from './select-language'

const dummyEvents = {
    switchBuildingBlockLanguage: 'switch building blocks language'
}

jest.mock(
    'cm/common/event-tracker',
    () => ({
        eventTracker: {
            track: () => {}
        },
        events: {
            dummyEvents
        }
    })
)

const languages = [
    {
        name: 'English',
        value: 'EN',
    },
    {
        name: 'Nederlands',
        value: 'NL'
    }
]

jest.mock(
    'cm/components/common/select',
    () => ({ items, handlers }) => {
        console.log('items', items)
        return (<div className="dropdown">
            <div className="dropdown__menu">
                {items.map(({ name }) => (
                    <div className="dropdown__item" onClick={handlers.onSelect}>{name}</div>
                ))}
            </div>
        </div>)
    }
)

const containerPath = '.dropdown'
const itemPath = '.dropdown__item'

describe('SelectLanguage component', () => {
    it('renders in the document', () => {
        const { container } = render(
            <SelectLanguage languages={languages}/>
        )

        const $container = container.querySelector(containerPath)

        expect($container).toBeTruthy()
    })

    it('renders items', () => {
        const { container } = render(
            <SelectLanguage languages={languages}/>
        )

        const $dropdownItems = container.querySelectorAll(itemPath)

        expect([ ...$dropdownItems ].length).toBe(2)
    })

    it('track select open click', () => {
        const spyFn = jest.fn()

        const { container } = render(
            <SelectLanguage
                selectedLanguage={{
                    value: 'EN'
                }}
                languages={languages}
                handlers={{
                    onSelect: spyFn
                }}
            />
        )

        const $dropdownItem = container.querySelector(itemPath)

        fireEvent.click($dropdownItem)

        expect(spyFn).toHaveBeenCalledWith(
            dummyEvents.switchBuildingBlockLanguage,
            {
                from: 'building blocks',
                language: 'en'
            }
        )
    })

    it('handles action', () => {
        const spyFn = jest.fn()

        const { container } = render(
            <SelectLanguage
                selectedLanguage={{
                    value: 'EN'
                }}
                languages={languages}
                handlers={{
                    onSelect: spyFn
                }}
            />
        )

        const $dropdownItem = container.querySelector(itemPath)

        fireEvent.click($dropdownItem)

        expect(spyFn).toHaveBeenCalledWith('EN')
    })
})

【问题讨论】:

    标签: reactjs unit-testing testing jestjs


    【解决方案1】:

    使用事件时,您需要等待它们完成后再运行断言。

    testing-library/react 有 waitFor function:

    import { fireEvent, render, waitFor } from '@testing-library/react'
    
    // ...
    
    
    it('handles action', async () => {
    
        // ...
    
        fireEvent.click($dropdownItem)
    
        await waitFor(() => {
            expect(spyFn).toHaveBeenCalledWith(
                dummyEvents.switchBuildingBlockLanguage,
                {
                    from: 'building blocks',
                    language: 'en'
                }
            )
        });
    
        // ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-08
      • 1970-01-01
      • 2021-12-03
      • 2018-01-26
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      • 2017-02-12
      相关资源
      最近更新 更多