如何用jest测试useImmer react钩子的setter?

9gm1akwq  于 11个月前  发布在  Jest
关注(0)|答案(1)|浏览(174)

我有一个父组件,其中一段状态是用useImer定义的,如下所示:

const [example, setExample] = useImmer({
submitterId: {
    value: EMPTY_STRING,
    label: 'Submitter ID',
    disabled: false,
    status: null,
    schema: submitterIdSchema
  },
  submitterName: {
    value: EMPTY_STRING,
    label: 'Submitter Name',
    disabled: false,
    status: null,
    schema: submitterNameSchema
  }});

字符串
这些状态被作为props传递给子组件,我正在尝试为子组件编写jest测试。这是一个简化的示例。

export function ChildComponent({
 example,
 setExample,
}) {

  const handleInputChange = async (e, fieldName) => {
    const valueToUpdateWith = e.target.value;
    const schema = example[fieldName].yupSchema;
    const status = await validate(valueToUpdateWith, schema);
   setExample((draft) => {
      draft[fieldName].status = status;
      draft[fieldName].value = valueToUpdateWith;
    });
  };

  return (
    <div id="exampleContainer">
      <ConnectedFieldGenerator // this just loops through keys in example and generates label/input field groups for them
        fieldKeys={Object.keys(example)}
        handleInputChange={handleInputChange}
      />
    </div>
  );
}


我写了下面的测试,以涵盖CNOSTInputChange函数,但在我的覆盖率报告中,setExample内部的逻辑没有涵盖。

const props = {
  example: EXAMPLE_INITIAL_FIELD_STATE,
  setExample: jest.fn(),
};

    describe('Search Table Renders', () => {
      it('input change of example', async () => {
        const { container } = render(<ChildComponent{...props} />);
        await enterInputValue(container, '#submitterId-input', 'Submitter ID');
        expect(props.setBasicSearchState).toHaveBeenCalled();
      });
    });


我如何在我的测试中覆盖下面的行?

setExample((draft) => {
  draft[fieldName].status = status; // NOT COVERED
  draft[fieldName].value = valueToUpdateWith; // NOT COVERED
});

ogq8wdun

ogq8wdun1#

您不需要模拟setExample函数,创建一个父组件用于测试目的。尽可能简单,为单个测试用例保留足够的逻辑。然后,将useImmer钩子返回的真实的setExample函数传递给<ChildComponent/>组件。最后,Assert组件呈现的最新状态。
例如
Child.jsx

import React from 'react';

export function ChildComponent({ example, setExample }) {
  const handleInputChange = async (e, fieldName) => {
    const valueToUpdateWith = e.target.value;
    const status = 'ok';
    setExample((draft) => {
      draft[fieldName].status = status;
      draft[fieldName].value = valueToUpdateWith;
    });
  };

  return (
    <div id="exampleContainer">
      <input type="text" onChange={(e) => handleInputChange(e, 'submitterId')} />
      <div>example.submitterId: {example.submitterId.value}</div>
      <div>example.submitterId.status: {example.submitterId.status}</div>
    </div>
  );
}

字符串
Child.test.jsx

import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { ChildComponent } from './Child';
import { useImmer } from 'use-immer';

describe('ChildComponent', () => {
  test('should pass', () => {
    // Component for testing purposes, keep it simple.
    const ParentComp = () => {
      const [example, setExample] = useImmer({
        submitterId: {
          value: '',
          label: 'Submitter ID',
          status: null,
        },
        submitterName: {
          value: '',
          label: 'Submitter Name',
          status: null,
        },
      });

      return <ChildComponent example={example} setExample={setExample} />;
    };
    render(<ParentComp />);
    const textbox = screen.getByRole('textbox');
    fireEvent.change(textbox, { target: { value: 'test' } });
    expect(screen.getByText('example.submitterId: test')).toBeInTheDocument();
  });
});


测试结果:

PASS  stackoverflow/77582125/Child.test.tsx                                                                                                                                                                                
  ChildComponent
    √ should pass (48 ms)                                                                                                                                                                                                   
                                                                                                                                                                                                                            
-----------|---------|----------|---------|---------|-------------------                                                                                                                                                    
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                                                                                                     
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 | 
 Child.tsx |     100 |      100 |     100 |     100 | 
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.736 s
Ran all test suites related to changed files.

相关问题