繁体   English   中英

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

[英]How to set an initial state using the useState hook

我使用 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()
    }
}

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

如何在笑话和酶中为 useState Hook 设置初始状态?

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

谢谢。

编辑:关于下面的答案:

传入 prop 不会改变我要测试的状态。

我有一个按钮,当点击(一种状态)时呈现一个输入框,当用户输入(另一种状态)并按下 OK 按钮(另一种状态)时,它会根据输入框中的内容创建一个按钮。

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

理想情况下,我想设置我的组件,设置用户在输入框中键入内容的状态,然后测试确定按钮是否执行了它应该执行的操作。 无需模拟之前的所有点击。

组件的状态在其内部,这是理解 React 组件的重要部分。 一旦你“理解”了它,你就可以理解任何测试都不应该试图改变它。

那么你如何为你的组件设置一个初始状态呢?

您将一个值传递给组件内部的useState钩子。 然后,您的测试应该使用该初始状态测试您的组件……他们应该只传入props来更改它,就像您的非测试代码一样。

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

同样,您永远不想测试您正在测试的任何东西的内部结构,无论是 React 组件还是其他任何东西。

如果你这样做,你编写的每个测试都会在这些内部发生任何变化的那一刻中断,而测试的一个重要价值在于它们让你更容易重构(如果测试内部)。 相反,您希望使用您的测试工具来衡量您的组件的输出(即它生成的 HTML)。

再说一次,这甚至与 React 无关。 任何东西的良好软件测试不会试图弄乱那个东西的内部结构,无论是改变还是衡量它们。 取而代之的是,好的测试侧重于externals ,因为同样是所有非测试代码都可以使用,并且因为从概念上讲,您测试的所有内容都应该是测试代码的“黑匣子”。

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

老实说,您的编辑并没有真正改变我的答案,只是它提醒我 Enzyme 确实有一种方法可以改变测试中的状态(我自己从来没有使用过,我忘记了它的存在)。

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

您想要测试的是外部部件,并且(根据您的编辑)它似乎不是props ……但它仍然是外部的东西:DOM。

所以我建议做的是(再次)非测试代码正在做的事情:“点击”你的按钮。 Enzyme 通过其“模拟”方法 ( https://airbnb.io/enzyme/docs/api/ReactWrapper/simulate.html ) 使这变得非常容易。

如果您只是模拟创建您想要的状态的按钮序列,您将只测试外部(即测试您的代码将在生产中使用的相同方式),但您将能够测试您想要的任何情况。

如何根据环境设置一个值? Jest 将环境变量NODE_ENV为“test”:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM