2

我正在尝试在我的组件上编写单元测试,它看起来像这样。

export const myComponent = ({text, list, getData = transport.getData}) => {
const [rows, setRows] = React.useState([]);

    React.useEffect(() => {
        const fetchData = async () => {
           const rows = await getData(list);
           setRows(rows);
        };
        fetchData();
    }, [list]);

    if (rows.length === 0) {
       return null;
    }

    return (
        // some JSX
    );
};

rows问题是组件通过 async 函数获取数据,所以在组件检查是否为空并返回 null后会调用它。

if (rows.length === 0) {
   return null;
}

我嘲笑getData所以它应该返回一些值。但是,我仍然不明白我应该如何用单元测试来覆盖这个组件。我想它应该是一个快照,也许它是不对的。

我的测试:

import React from 'react';
import {myComponent} from '../components/myComponent';
import renderer from 'react-test-renderer';

describe('myComponent', () => {
    test('should renders correctly', async () => {
        const mock = {
            text: 'text',
            list: [],
            getData: () =>
                Promise.resolve([
                    {
                        // ...
                    },
                ]),
        };
        const component = renderer.create(<myComponent text={mock.text} 
list={mock.list} getData={mock.getData}/>);
        let popup = component.toJSON();
        expect(popup).toMatchSnapshot();
    });
});
4

1 回答 1

0

这是单元测试解决方案:

index.tsx

import React from 'react';

const transport = {
  async getData(list) {
    return [{ id: 1 }];
  }
};

export const MyComponent = ({ text, list, getData = transport.getData }) => {
  const [rows, setRows] = React.useState<any[]>([]);

  React.useEffect(() => {
    console.count('useEffect');
    const fetchData = async () => {
      console.count('fetchData');
      const newRows = await getData(list);
      setRows(newRows);
    };
    fetchData();
  }, [list]);

  if (rows.length === 0) {
    return null;
  }

  return <div>rows count: {rows.length}</div>;
};

index.spec.tsx

import React from 'react';
import { MyComponent } from './';
import renderer, { act } from 'react-test-renderer';

describe('myComponent', () => {
  test('should renders correctly', async () => {
    const mProps = {
      text: 'text',
      list: [],
      getData: jest.fn().mockResolvedValueOnce([{ id: 1 }, { id: 2 }, { id: 3 }])
    };
    let component;
    await act(async () => {
      component = renderer.create(<MyComponent {...mProps}></MyComponent>);
    });
    expect(component.toJSON()).toMatchSnapshot();
  });
});

单元测试结果:

PASS  src/stackoverflow/57778786/index.spec.tsx
  myComponent
    ✓ should renders correctly (29ms)

  console.count src/stackoverflow/57778786/index.tsx:13
    useEffect: 1

  console.count src/stackoverflow/57778786/index.tsx:15
    fetchData: 1

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        3.557s, estimated 8s

index.spec.tsx.snap

// Jest Snapshot v1

exports[`myComponent should renders correctly 1`] = `
<div>
  rows count: 
  3
</div>
`;

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57778786

于 2019-11-11T05:32:44.097 回答