代码之家  ›  专栏  ›  技术社区  ›  Anshu Verma

使用Jest和酶测试内部使用效果

  •  0
  • Anshu Verma  · 技术社区  · 2 年前

    useEffect ,这是我的密码

    const RatingsAndReviews = (props: RatingsAndReviewsProps) => {
    
    const [pageLoaded, setPageLoaded] = useState<boolean>(false)
    
    const handleLoad = () => {
        if (document.readyState === 'complete') {
          setTimeout(() => {
            setPageLoaded(true)
          }, 1500)
        }
    }
    
    React.useEffect(() => {
        window.addEventListener('load', handleLoad)
        return () => {
          window.removeEventListener('load', handleLoad)
        }
    }, [])
    
    return (...some code)
    }
    

    我想测试一下 handleLoad 函数,但我不知道如何在我的组件中传递这个模拟函数,因为组件已经需要道具了,而且它是TypeScript,所以除了必需的道具之外,我不能传递任何其他东西,这是我的测试用例

    it('Should run handleLoad function onMount', ()=>{
        jest.spyOn(React, 'useEffect').mockImplementation(f => f())
        const handleLoad = jest.fn();
        wrapper = mount(<RatingsAndReviews {...propObj} />)
        expect(handleLoad).toHaveBeenCalled();
    })
    

    我犯了这个错误 expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0
    
    0 回复  |  直到 2 年前
        1
  •  0
  •   Lin Du    2 年前

    尽量不要模拟第三方库函数的实现,因为不正确的模拟实现会破坏其功能。例如 useEffect(effect) react钩子不只是执行 effect 作用考虑

    反应推迟了跑步 useEffect 直到浏览器绘制完毕。

    你怎么嘲笑它?不正确的模拟将导致意外行为。基于不正确的模拟实现,您的测试可能会通过,但代码在实际运行时会失败。这就是为什么你最好不要嘲笑第三方库。当然,这不是绝对的。如果第三方库的功能简单且自包含,则可以对其进行模拟。

    对于React组件,我们应该进行黑盒测试,只测试组件的行为和功能,而不是实现。我们应该将组件视为一个单元,而不是其中的函数。

    我们应该测试当 pageLoaded 州变了。

    函数组件内部定义的事件处理程序是私有的,您不能从外部访问它们(测试代码)。所以你不能直接调用它们。相反,您应该通过用户事件触发它们。这个 load 为你的案子准备的活动。

    例如。

    index.tsx :

    import React from 'react';
    import { useEffect, useState } from 'react';
    
    export const RatingsAndReviews = (props) => {
      const [pageLoaded, setPageLoaded] = useState<boolean>(false);
    
      console.log('pageLoaded: ', pageLoaded);
      const handleLoad = () => {
        if (document.readyState === 'complete') {
          setTimeout(() => {
            setPageLoaded(true);
          }, 1500);
        }
      };
    
      useEffect(() => {
        window.addEventListener('load', handleLoad);
        return () => {
          window.removeEventListener('load', handleLoad);
        };
      }, []);
    
      return <div>{pageLoaded ? 'loaded' : 'not loaded'}</div>;
    };
    

    index.test.tsx :

    import { mount } from 'enzyme';
    import React from 'react';
    import { act } from 'react-dom/test-utils';
    import { RatingsAndReviews } from '.';
    
    describe('RatingsAndReviews', () => {
      it('Should run handleLoad function onMount', () => {
        jest.useFakeTimers();
        const wrapper = mount(<RatingsAndReviews />);
        window.dispatchEvent(new Event('load'));
        expect(wrapper.text()).toBe('not loaded');
        act(() => {
          jest.advanceTimersByTime(1500);
        });
        expect(wrapper.text()).toBe('loaded');
      });
    });
    

    测试结果:

     PASS  stackoverflow/71953030/index.test.tsx (11.883 s)
      RatingsAndReviews
        ✓ Should run handleLoad function onMount (47 ms)
    
      console.log
        pageLoaded:  false
    
          at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)
    
      console.log
        pageLoaded:  true
    
          at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |   93.33 |       75 |      80 |   92.86 |                   
     index.tsx |   93.33 |       75 |      80 |   92.86 | 19                
    -----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        13.575 s, estimated 14 s
    

    软件包版本:

    "enzyme": "^3.11.0",
    "enzyme-adapter-react-16": "^1.15.5",
    "react": "^16.14.0",
    "react-dom": "^16.14.0",
    "jest": "^26.6.3",