首页 > 解决方案 > 测试组件使用自定义钩子 react-testing-library

问题描述

我正在使用 react-testing-library 使用自定义钩子测试我的组件。但我不能让它过去。这是我的代码

function useInput<T>(): Return<T> {
    const [input, setInput] = useState<T>({} as T);
    const [isDirty, setDirty] = useState({} as Record<keyof T, boolean>);

    const handleInputChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        setInput({
            ...input,
            [e.target.name]: e.target.value
        });
        setDirty({
            ...isDirty,
            [e.target.name]: true
        });
    };

    const resetInput = () => {
        Object.keys(input).map((v) => (input[v as keyof T] as unknown as string) = '');
        Object.keys(isDirty).map((v) => (isDirty[v as keyof T] as unknown as string) = '');
        setInput({...input});
        setDirty({...isDirty});
    };

    return [input, handleInputChange, isDirty, resetInput, setInput]
}

const Login: React.FC = () => {
    const [input, handleChangeInput, isDirty, resetInput] = useInput<IInput>();

    return (
                <input
                    value={input.username}
                    onChange={handleChangeInput}
                    name={'username'}
                    className={classNames(`shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline`)}
                    id={'username'} type={'text'} placeholder={'Username'}/>

    )
}

测试

import React from "react";
import {render, unmountComponentAtNode} from "react-dom";
import Login from './index'
import {renderHook, act as actHook} from '@testing-library/react-hooks'
import {MemoryRouter} from "react-router-dom";
import {useInput} from '../hooks';
import { fireEvent } from '@testing-library/react';


describe('test login', () => {
  it('to match snapshot', () => {
    render(
      <MemoryRouter>
        <Login/>
      </MemoryRouter>
      ,
      container);
    expect(container).toMatchSnapshot()
  });

  it('input correct when change username',  () => { //can't pass
     render(
      <MemoryRouter>
        <Login/>
      </MemoryRouter>
      ,
      container);

    const {result} = renderHook(() => useInput());
    const [input, handleChangeInput] = result.current;
    const inputName = container.querySelector('#username');
    fireEvent.change(inputName, {target: {value: 'test'}});

    actHook(() => {
      handleChangeInput({target: {name: 'username', value: 'test'}});
    });
    expect(input).toBe({
      username: 'test'
    })

  })
});

我的脚本测试是。当输入 fireEvent 调用时,输入变化值和钩子 useInput 中的值具有相同的值。但我可以让它过去。我哪里错了?请帮忙

标签: javascriptreactjsreact-testing-library

解决方案


创建 React hooks 测试库是为了测试 hooks ,而无需将其安装在测试组件上。您必须决定测试钩子本身(不使用您的登录组件)或整个组件 - 那么您根本不需要钩子测试库 - react-testing-library 就足够了。您的fireEvent实际上在没有以下部分的情况下“触发”了您的钩子

const {result} = renderHook(() => useInput());
const [input, handleChangeInput] = result.current;

推荐阅读