我使用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呢?
理想情况下,我想设置我的组件,设置用户在输入框中键入的状态,然后测试以查看“确定”按钮是否按预期执行操作。无需模拟之前的所有点击。
答案 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)