Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何模拟要测试的React组件内部的自定义钩子?_Reactjs_Unit Testing_React Hooks - Fatal编程技术网

Reactjs 如何模拟要测试的React组件内部的自定义钩子?

Reactjs 如何模拟要测试的React组件内部的自定义钩子?,reactjs,unit-testing,react-hooks,Reactjs,Unit Testing,React Hooks,如果您有一个React组件调用一个获取数据的自定义钩子,那么在测试React组件时模拟内部自定义钩子结果的最佳方法是什么?我看到两种主要方法: 1) 开玩笑。模仿定制挂钩。这似乎是最推荐的方法,但它似乎要求测试对内部实现细节和可能需要模拟的内容有更多的了解,而不是组件的props接口可能建议的内容(假设使用prop类型或TypeScript) 2) 使用依赖注入方法。将钩子声明为道具,但将其默认为真实钩子,这样您就不必在渲染组件的任何地方都设置钩子,而是允许使用模拟覆盖以进行测试。下面是一个虚构

如果您有一个React组件调用一个获取数据的自定义钩子,那么在测试React组件时模拟内部自定义钩子结果的最佳方法是什么?我看到两种主要方法:

1) 开玩笑。模仿定制挂钩。这似乎是最推荐的方法,但它似乎要求测试对内部实现细节和可能需要模拟的内容有更多的了解,而不是组件的props接口可能建议的内容(假设使用prop类型或TypeScript)

2) 使用依赖注入方法。将钩子声明为道具,但将其默认为真实钩子,这样您就不必在渲染组件的任何地方都设置钩子,而是允许使用模拟覆盖以进行测试。下面是一个虚构的codesandbox示例,其中有一个模拟自定义挂钩的测试:


2需要更多的输入,但似乎更容易用于测试。然而,测试必须了解组件的内部实现细节,才能测试渲染输出的任何条件逻辑,所以这可能并不重要,1是最好的方法。1路走吗?你看到了什么权衡?我是否完全错过了另一种方法?

对于mocking hook本身,您永远不知道真正的方法是否能与您的组件一起很好地工作


用传球钩子作为支撑,钩子之间很难沟通。例如,当您需要自定义钩子从同一组件调用setter时
useState
。您需要使用越来越多的参数扩展自定义钩子

  • 您可以模拟外部API调用-我的意思是模拟
    fetch
    XHR
    。它仍然需要知道一些实现细节——您正在运行HTTP请求的事实——但是您的测试应该知道的事情很少

  • 为什么不模拟进行api调用的底层方法呢


    例如,如果您正在使用
    fetch()
    检索数据,您可以模拟它。通过这种方式,您可以为该调用定义自定义响应,这将使测试挂钩本身变得简单

    这个问题已经问了几个月了,但是如果你还没有找到一个好的解决方案,我写了一个可能会有所帮助的包。我经历了一个类似的思考过程,包括“如果我将钩子注入组件会怎么样?”事情变得很奇怪

    我基本上想要一个连接器,以避免仅仅为了测试它们而为表现性组件提供额外的包装

    我提出了
    react hooks compose
    ,它允许您将挂钩和演示者分开,并单独或一起进行测试:

    export const useFetch=()=>{
    const[user,setUser]=useState();
    useffect(()=>{
    fetchData('some-url')//setUser(res.data));
    }, []);
    返回{user};
    }
    //composeHooks将钩子中的值作为道具传递
    export const UserPresenter=({user})=>{
    返回为{user.name}获取的数据;
    }
    导出默认composeHooks({useFetch})(DataPresenter);
    
    现在,您不必模拟挂钩,只需使用道具测试演示者:

    it('presents user',()=>{
    常量{queryByText}=render();//{
    fetchData.mockResolvedValue('Mary');
    常量{queryByText}=render();//{
    expect(queryByText('Mary')).toBeTruthy();
    });
    });
    

    如果愿意,您甚至可以对钩子进行单元测试。

    使用jest模拟自定义钩子

    import * as useCustomHook from '../hooks/useCustomHooks'
    
    const spy = jest.spyOn(useCustomHook, 'default')
    spy.mockReturnValue({
    name: 'test'
    })
    

    这样做不再是一个单元测试。组件不应该关心如何检索数据的实现细节;这是钩子函数的工作。如果以后决定更改钩子的实现,则必须重构所有使用钩子的测试。这也可能会失控。想象一下,如果钩子获得数据,它会自动恢复从另一个从
    useContext
    读取的钩子访问api。我一直在想同样的事情。在引入React钩子之前,我使用recompose大约一年了,我喜欢它为解耦和简单的单元测试所做的工作。Andrew Clark(recompose)我也研究过React钩子,并建议在重新组合时使用它,但我还没有看到展示相同解耦能力的像样的例子。有没有人有像样的例子来说明如何以与重新组合方法HoCs相同的方式处理钩子?是的,不久前遇到过这个包,但忘记了更新这个问题。谢谢!很高兴看到这个问题“听到了!”使用传递钩子作为道具,让钩子彼此通信将非常困难。“这与从模块导入钩子有什么不同?您仍然不能使用。例如
    useState
    setter如果导入,可以吗?除非您将其作为参数传递给钩子。如果您注入钩子,也可以这样做。”