如何测试依赖于 useContext 钩子的反应组件? [英] How to test a react component that is dependent on useContext hook?

查看:17
本文介绍了如何测试依赖于 useContext 钩子的反应组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 useContext 的组件,然后它的输出取决于上下文中的值.一个简单的例子:

I have a component that uses useContext and then its output is dependent on the value in the context. A simple example:

import React, { useContext } from 'react';

const MyComponent = () => {
  const name = useContext(NameContext);

  return <div>{name}</div>;
};

使用来自 react 和 jest 快照的浅层渲染器测试此组件时.如何更改 NameContext 的值?

When testing this component with the shallow renderer from react and jest snapshots. How can I change the value of NameContext?

推荐答案

一般来说,使用钩子不应该改变太多的测试策略.这里更大的问题实际上不是钩子,而是上下文的使用,这让事情有点复杂.

In general, using hooks shouldn't change testing strategy much. The bigger issue here actually isn't the hook, but the use of context, which complicates things a bit.

有很多方法可以使这项工作,但我发现的唯一方法是注入一个模拟钩子:

There's a number of ways to make this work, but only approach I've found that works with 'react-test-renderer/shallow' is to inject a mock hook:

import ShallowRenderer from 'react-test-renderer/shallow';

let realUseContext;
let useContextMock;
// Setup mock
beforeEach(() => {
    realUseContext = React.useContext;
    useContextMock = React.useContext = jest.fn();
});
// Cleanup mock
afterEach(() => {
    React.useContext = realUseContext;
});

test("mock hook", () => {
    useContextMock.mockReturnValue("Test Value");
    const element = new ShallowRenderer().render(
        <MyComponent />
    );
    expect(element.props.children).toBe('Test Value');
});

不过,这有点脏,并且是特定于实现的,因此如果您能够在浅层渲染器的使用上妥协,还有一些其他选项可用:

This is a bit dirty, though, and implementation-specific, so if you're able to compromise on the use of the shallow renderer, there's a few other options available:

如果你不是浅渲染,你可以把组件包装在一个上下文提供者中来注入你想要的值:

If you're not shallow rendering, you can just wrap the component in a context provider to inject the value you want:

import TestRenderer from 'react-test-renderer';

test("non-shallow render", () => {
    const element = new TestRenderer.create(
        <NameContext.Provider value="Provided Value">
            <MyComponent />
        </NameContext.Provider>
    );
    expect(element.root.findByType("div").children).toEqual(['Provided Value']);
});

(免责声明:这应该可以工作,但是当我测试它时,我遇到了一个错误,我认为这是我的设置中的一个问题)

(Disclaimer: this should work, but when I test it, I'm hitting an error which I think is an issue in my setup)

正如@skyboyer 所评论的,酶的浅层渲染器支持 .dive 允许您深入渲染原本浅层渲染组件的一部分:

As @skyboyer commented, enzyme's shallow renderer supports .dive allowing you to deeply renderer a part of an otherwise shallow rendered component:

import { shallow } from "./enzyme";

test("enzyme dive", () => {
    const TestComponent = () => (
        <NameContext.Provider value="Provided Value">
            <MyComponent />
        </NameContext.Provider>
    );
    const element = shallow(<TestComponent />);
    expect(element.find(MyComponent).dive().text()).toBe("Provided Value");
});

使用 ReactDOM

最后,Hooks 常见问题 有一个使用 ReactDOM 测试钩子的例子,它也能工作.自然,使用 ReactDOM 意味着这也是深度渲染,而不是浅渲染.

Use ReactDOM

Finally, the Hooks FAQ has an example of testing hooks with ReactDOM, which works as well. Naturally, using ReactDOM means this is also a deep render, not shallow.

let container;
beforeEach(() => {
    container = document.createElement('div');
    document.body.appendChild(container);
});

afterEach(() => {
    document.body.removeChild(container);
    container = null;
});

test("with ReactDOM", () => {
    act(() => {
        ReactDOM.render((
            <NameContext.Provider value="Provided Value">
                <MyComponent />
            </NameContext.Provider>
        ), container);
    });

    expect(container.textContent).toBe("Provided Value");
});

这篇关于如何测试依赖于 useContext 钩子的反应组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆