React+Jest - 测试异步组件并等待挂载

cas*_*raf 3 javascript reactjs jestjs enzyme

我正在尝试测试具有 async 的 React 组件componentDidMount

承诺本身不需要被嘲笑,它不一定用于访问外部内容,主要只是道具的包装。

但是,为了测试它,我需要使用wrapper.update() 4 次,这对我来说似乎很奇怪。

解决方案在:

一切都不适合我。

这是我的测试的样子(目前有效,但这个解决方案一点也不优雅,而且可扩展性也不强):

import * as React from 'react'
import { shallow, mount } from 'enzyme'
import LargeSelector from './LargeSelector'

describe('<LargeSelector />', async () => {
    const componentDidMountSpy = jest.spyOn(LargeSelector.prototype, 'componentDidMount')

    describe('search', async () => {
        it('should save initial response in cache', async () => {
            const wrapper = await shallow(<LargeSelector query={async (search) => ['search:' + search]} />)

            // WHY DO I NEED 4 UPDATES???
            await wrapper.update()
            await wrapper.update()
            await wrapper.update()
            await wrapper.update()

            expect(LargeSelector.prototype.componentDidMount).toHaveBeenCalledTimes(1) // works fine
            // these 2 only pass the expectation if I call wrapper.update() no less than 4 times    
            expect(wrapper.state()).toHaveProperty('options', ['search:'])
            expect(wrapper.state()).toHaveProperty('initialOptions', ['search:'])
        })
    })
})
Run Code Online (Sandbox Code Playgroud)

以下是componentDidMountand的实现filterResults(调用前者):

public async componentDidMount() {
    if (this.props.searchOnInit) {
        const results = await this.filterResults('', [])
        if (this.props.cacheInitialResponse) {
            this.setState({ initialOptions: results })
        }
    }
}

private async filterResults(search: string, filters: IFilter[]) {
    const results = await this.props.query(search, filters)
    this.setState({ options: results })
    return results
}
Run Code Online (Sandbox Code Playgroud)

小智 5

我面临着完全相同的问题。问题是测试不会等待承诺的实现。我的解决方案是使用 Jest 提供的 done 回调来表示测试结束。

像这样:

it('wait async code before assert something', (doneCallback) => {
    const wrapper = shallow(<Component />);

    setImmediate(() => {
        expect(wrapper.find('.async').length).toBe(1);
        doneCallback();
    });
});
Run Code Online (Sandbox Code Playgroud)