【问题标题】:React testing `useEffect` with `useState` update使用 useState 更新反应测试 useEffect
【发布时间】:2023-02-01 15:53:05
【问题描述】:

在我的组件渲染中,我的 useEffects 挂钩调用了一个函数。该函数根据 useEffects 产生的条件更新状态。

那么在这种情况下如何测试 `mobileMenu` 以及如何在 useEffect 中设置不同的条件来测试它呢?

我希望我的useEffectsuseState 都需要被嘲笑。我正在学习反应过程。搜索后我无法得到任何正确答案,请有人帮助我吗?

这是我的app.tsx

我的 ts 文件:

import { Footer, Header, ProductCart, ProductPhotoGallery, Tabs } from '@mcdayen/components';
import { Cart, Logo, MobileMenu, NaviLinks, QuickSearch, User } from '@mcdayen/micro-components';
import { initialNaviLinksProps, initialPhotoProps, initialTabsProps, NaviLinksProps, sizeProps } from '@mcdayen/prop-types';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchCartDetails, sizeHandler } from './store/cart.slice';
import { AppDispatch, RootState } from './store/store.config';

export function App() {
    const dispatch:AppDispatch = useDispatch();
    dispatch(fetchCartDetails());
    const {product} = useSelector((state:RootState) => state.cartStore)
    const [mobileMenu, setMobileMenu] = useState<boolean>(false);
    const [linkProps, setLinkProps] = useState<NaviLinksProps | null>(null);

    function mobileMenuHandler() {
        setMobileMenu((current: boolean) => !current);
    }

     useEffect(() => {
        setLinkProps(initialNaviLinksProps);
        const mobileId = document.getElementById('mobileMenu');
         if (mobileId?.offsetParent) {
            mobileMenuHandler();
        }
     }, []);
    
    useEffect(() => {
        setLinkProps((props) => {
            return mobileMenu ? { ...initialNaviLinksProps } : { ...initialNaviLinksProps, classProps: props?.classProps + ' hidden' }
        })
    }, [mobileMenu]);

    function onSizeSelect(selectedSize: sizeProps) {
        dispatch(sizeHandler(selectedSize));
    }
    
    return (
        <section  className="box-border m-auto flex flex-col pl-[18px] py-6   min-h-screen flex-wrap px-5 md:container md:w-[1440px] md:pl-[70px] pr-5 ">
            <Header>
                <Logo />
                {linkProps && <NaviLinks passNaviLinks={linkProps} />}
                <div className="flex gap-3">
                    <QuickSearch />
                    <Cart />
                    <User />
                    <MobileMenu menuHandler={mobileMenuHandler} />
                </div>
            </Header>
            <main  className='flex flex-col justify-between lg:flex-row'>
                <div className='hidden lg:block w-[325px]'>
                    <div>
                        <Tabs tabProps={initialTabsProps}  />
                    </div>
                </div>
                <div className='grow-0 flex-auto' >
                   {initialPhotoProps.length && <ProductPhotoGallery gallery={initialPhotoProps} />}
                </div>
                <div className='flex bg-white'>
                    {product && <ProductCart sizeSelect={onSizeSelect}  passCartProps={product} />}
                </div>
            </main>
            <Footer />
        </section>
    );
}

export default App;

我的规格:


import { configureStore } from '@reduxjs/toolkit';
import { render } from '@testing-library/react';
import React from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import App from './app';
import cartReducer from './store/cart.slice';

jest.mock('react', () => ({
  ...jest.requireActual('react'),
  useState: jest.fn(),
}));

export function createTestStore() {
  const store = configureStore({
        reducer: {
        cartStore:cartReducer,
        }
    })
  return store;
}

describe('App', () => {
     const setMobileMenu = jest.fn();
  const useStateMock = (initState: boolean) => [initState, setMobileMenu];

  jest.spyOn(React, 'useState').mockImplementation(useStateMock);

  afterEach(() => {
    jest.clearAllMocks();
  });
    const store = createTestStore();
    it('should render successfully', () => {
        const { baseElement } = render(
            <BrowserRouter>
                <Provider store={store}>{<App />}</Provider>
            </BrowserRouter>
        );
        expect(baseElement).toBeTruthy();
        useStateMock(true);
        expect(setMobileMenu).toHaveBeenCalledWith(true);
    });
});

我在以下位置收到错误消息:`

jest.spyOn(React, 'useState').mockImplementation(useStateMock);

`

如:Argument of type '(initState: boolean) =&gt; (boolean | jest.Mock&lt;any, any&gt;)[]' is not assignable to parameter of type '() =&gt; [unknown, Dispatch&lt;unknown&gt;]'.

我的测试失败了。

需要帮助:

  1. 在匿名函数上测试 useEffect 挂钩(模拟)

  2. 修复突出显示的错误

  3. 测试 setMobileMenu 上的状态

    任何人请用正确的方法帮助我吗?

【问题讨论】:

    标签: reactjs typescript jestjs react-testing-library react-testing


    【解决方案1】:

    尝试将 useStateMock 声明为:

    const useStateMock = (initState: any) => [initState, setMobileMenu];
    

    【讨论】:

      猜你喜欢
      • 2021-04-19
      • 2023-02-16
      • 2019-10-14
      • 2021-09-06
      • 2020-10-16
      • 2020-10-20
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多