如何在 Jest 和 Enzyme 中执行无状态组件内的函数以进行测试

Posted

技术标签:

【中文标题】如何在 Jest 和 Enzyme 中执行无状态组件内的函数以进行测试【英文标题】:How to Execute a Function Inside a Stateless Component for Testing in Jest and Enzyme 【发布时间】:2019-06-06 03:01:06 【问题描述】:

我有一个用 Recompose withHandlers HOC 封装的父组件。我有一个名为 removeGiftHandler 的函数,我想将它作为回调传递给子组件,该回调将更改父组件中 props 中保存的状态(使用 withState)。

我目前正在测试父组件,特别是removeGiftHandler 函数。问题是因为函数被传递给子组件,所以我没有要模拟的事件。此外,如果它是一个类组件,我可以使用 wrapper.instance().removeGift(id) 并且不会有问题。鉴于它是一个无状态的功能组件,情况并非如此。

这是组件的代码:

const App = ( addGiftHandler, state:  gifts  ) => (
    <div>
        <h1>Gift Giver</h1>
        <ListGroup>
            map(
                ( id ) => (
                    <ListGroupItem key=id>
                        <Gift />
                    </ListGroupItem>
                ),
                gifts
            )
        </ListGroup>
        <Button outline onClick=addGiftHandler>
            Add Gift
        </Button>
    </div>
)

export default compose(
    withEnhancedState(INITIAL_STATE),
    withHandlers(
        addGiftHandler: ( state:  gifts , updateState ) => () =>
            updateState( gifts: [...gifts,  id: inc(length(gifts)) ] ),
        removeGiftHandler: ( state:  gifts , updateState ) => id => () =>
            updateState( gifts: filter(gift => gift.id !== id, gifts) ),
    )
)(App)

一旦removeGiftHandler 被正确测试,计划将其传递给Gift 组件。

以下是测试的相关代码:

import React from 'react'
import  shallow  from 'enzyme'
import  length  from 'ramda'

import App from '.'

const getBaseApp = app =>
    app
        .dive()
        .dive()
        .dive()

describe('App', () => 
    const app = shallow(<App />)
    const baseApp = getBaseApp(app)

        //...

        describe('and the user wants to remove the added gift', () => 
            beforeEach(() => 
                //-----> trigger removeGiftHandler somehow <-----
            )

            it('removes the gift from `state`', () => 
                expect(app.props().state.gifts).toEqual([])
            )
        )
    )
)

注意baseApp 是没有 Recompose HOC 的基本组件。

有人可以帮我解决这个问题吗?

【问题讨论】:

也许你可以只潜水 2 次而不是 3 次,所以你会得到 withHandlers 部分并调用该函数并检查状态是否已更新,但我不确定这是否有效。我们的做法是将视图从重组中分离出来,所以我们只返回一个文件而不是返回compose(...)(Component),一个文件返回compose(...),一个文件返回组件和一个index.js,它只返回logic(View)。通过这种方法,我们可以轻松地测试重构部分和隔离的渲染功能。 如何分别测试 compose(...) 部分? 看看这个要点:gist.github.com/eskimoblood/20fcc8b7994c1abcb192a07936885a4f @AndreasKöberle Diving 两次确实有效。感谢您花时间编写要点。很抱歉我没有早点回复你。我一定会单独记住这种测试 compose(...) 的模式,以防将来需要使用它。 好的,我会提供它作为答案。 【参考方案1】:

您需要潜水 2 次而不是 3 次才能到达withHandlers HOC。在 props 上,您可以调用该函数并检查状态是否正确更新。

【讨论】:

以上是关于如何在 Jest 和 Enzyme 中执行无状态组件内的函数以进行测试的主要内容,如果未能解决你的问题,请参考以下文章

Jest / Enzyme - 如何在不同的视口进行测试?

如何使用 Jest/Enzyme 在功能性 React 组件中测试 lambda 函数?

如何使用 Jest 和/或 Enzyme 获取嵌套在 React 组件中的元素的属性?

ReactWrapper::state() 只能在类组件单元测试 Jest 和 Enzyme 上调用

如何在 Enzyme / Jest Test 中切换和检查 Material UI 复选框

如何使用 JEST、Enzyme 在 React 中测试自定义钩子?