如何使用useState挂钩设置初始状态

时间:2020-02-03 15:29:06

标签: reactjs jestjs react-hooks

我使用useState钩子编写了一个功能组件,该组件本身可以正常工作,但是在测试时遇到了麻烦。我不明白如何在组件中创建初始状态。我尝试了多种模拟useState的方法,但都无效:

describe('<Component/>', () => {
    beforeEach() = > {
        jest.spyOn(Readt, 'useState').mockImplementation( () => React.useState(['test']));
        //Also tried this:
        //React['useState'] = jest.fn().mockImplementation( () => React.useState(['test']));
    }
    it('should match snapshot', () => {
        expect(wrapper).toMatchSnapshot()
    }
}

我也看过这篇文章,但无法为我工作

How to set initial state for useState Hook in jest and enzyme?

我还读到您不应该在单元测试中模拟出useState,但是如果您不模拟出它,那么如何为组件设置初始状态呢?

谢谢。

编辑: 关于以下答案:

传递道具不会改变我要测试的状态。

我有一个按钮,当单击(一个状态)时,将呈现一个输入框,当用户键入(另一个状态)并按“确定”按钮时(另一个状态),该输入框将根据输入框中的内容创建一个按钮

传递的道具有助于呈现按钮列表,但不能控制用户在输入框中键入的内容。我试图在输入框中设置一个状态,然后模拟单击“确定”按钮并进行测试。我不是要测试反应本机useState功能。我只是想使用已经具有“ wrapper.setState”的酶,但是如何使用useState呢?

理想情况下,我想设置我的组件,设置用户在输入框中键入的状态,然后测试以查看“确定”按钮是否按预期执行操作。无需模拟之前的所有点击。

2 个答案:

答案 0 :(得分:2)

一个组件的状态是它的内部,这是理解React组件的一个必要部分。一旦“理解”了这一点,便可以理解,没有任何测试可以尝试更改它。

但是您如何为组件设置初始状态?

您将值传递到您的useState挂钩中,在组件内部。然后,您的测试应该使用该初始状态来测试您的组件……它们应该像传入非测试代码一样,通过 props 对其进行更改。

实际上,即使您可以某种方式更改初始状态(这是AFAIK都不可能的),您的测试代码也绝不能做非测试代码所要做的任何事情(设置模拟 的测试环境除外)真实的代码),因为进行测试的整个过程都是为了验证您的非测试代码是否有效。

类似地,您永远都不想测试正在测试的任何东西的内部,无论它是React组件还是其他任何东西。

如果这样做,您编写的每个测试都会在这些内部结构发生任何变化时中断,并且测试价值的巨大部分在于,它们使您可以更轻松地进行重构( if 您< em>不要测试内部)。相反,您想使用测试工具来测量组件的输出(即,组件生成的HTML)。

再说一次,这真的与React无关。对任何东西进行良好的软件测试,都不会试图改变或评估它们的内部结构。相反,好的测试应该集中在外部上,因为这又是每个人都可以使用的所有非测试代码,并且从概念上讲,您测试的所有内容都应该成为测试代码的“黑匣子”。

编辑:对评论/问题的回复

说实话,您的编辑并没有真正改变我的回答,只是它提醒我酶确实可以更改测试中的状态(我自己从未使用过它,我忘记了它的存在)。

但是,再次,仅仅因为可能的事情并不意味着它是一个好主意,并且再次,您想测试您测试的任何东西 exterior (而不仅仅是反应组件)。 React组件的状态就像一个函数内部的变量:在该函数/组件的内部 ,应避免直接测试

您要测试的是 exterior 片断,并且(根据您的编辑)似乎不是props ...但是它仍然是外部的:DOM

因此,我反而建议做的是(再次)非测试代码正在做的相同事情:“单击”按钮。酶通过其“模拟”方法(https://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html)使其非常容易。

如果仅模拟创建所需状态的按钮序列,则仅测试外部(即,以与生产中使用的方式相同的方式测试您的代码),但是您可以在任何情况下进行测试你想要的。

答案 1 :(得分:-1)

如何根据环境设置值? Jest将环境变量NODE_ENV设置为'test':

const inTest = process.env.NODE_ENV === 'test'

[value, setValue] = useState(inTest ? mockValue : defaultValue)