React Native异步Jest组件测试

时间:2019-06-17 08:24:37

标签: javascript react-native asynchronous testing jestjs

我有一个组件,该组件在安装时调度fetch请求,并显示结果。

在请求完成后,我正在尝试为此组件创建测试快照。我已经为此花了很长时间了,这是关于SO的相关问题,这让我没有运气:

  1. Async component snapshot using Jest and Redux
  2. How do test async components with Jest?
  3. React+Jest - Testing async components and waiting for mount
  4. How to take a jest snapshot after axios fetched data in componentDidMount?

这是我的fetch模拟:

// Mocking the global.fetch included in React Native
global.fetch = jest.fn()

// Helper to mock a success response (only once)
fetch.mockResponseSuccess = (body, status = 200) => {
    fetch.mockImplementationOnce(() =>
        Promise.resolve({
            status,
            json: () => Promise.resolve(JSON.parse(body))
        })
    )
}

// Helper to mock a failure response (only once)
fetch.mockResponseFailure = error => {
    fetch.mockImplementationOnce(() => Promise.reject(error))
}

组件(简体):

export class Posts extends Component {
    constructor(props) {
        super(props)
        this.state = {
            items: [],
            loading: false
        }
        this._getItems()
    }

    async _getItems() {
        const resp = await fetch(
                "/user/recent_posts",
                {
                    method: "GET"
                }
            )
        this.setState({
            items: resp.json["data"],
        })
    }

    render() {
        // renders this.state.items
    }

这是测试:

    test("view renders correctly", async done => {
        fetch.mockResponseSuccess(
            JSON.stringify({
                data: [
                    { caption: "test", likes: 100 },
                    { caption: "test2", likes: 200 }
                ]
            })
        )
        // also tried with setTimeout and setImidiate
        const wrapper = await shallow(<Posts />) // also tried with react-test-renderer
        await wrapper.update() // didn't work with or without
        // await waitForState(wrapper, state => state.loading === false) --> didn't work
        // process.nextTick(() => {.... --> didn't work
        // jest.runTimersToTime(1) --> didn't work
        expect(wrapper).toMatchSnapshot()
        done()
    })

问题在于快照中的this.state.items始终为空。

1 个答案:

答案 0 :(得分:0)

为将来参考,以下是为我解决的问题:

test("view renders correctly", done => {
    // mock response here...
    const wrapper = shallow(<Posts />)
    setImmediate(() => {
        wrapper.update()
        try {
            expect(wrapper).toMatchSnapshot()
        } catch (e) {
            console.log(e)
        }

        done()
    })
})