如何测试道具是否传递给孩子? [英] How can I test if a prop is passed to child?

查看:17
本文介绍了如何测试道具是否传递给孩子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的组件看起来像这样:(它有更多的功能和列,但为了使示例更简单,我没有包括它)

const WeatherReport:FunctionComponent= ({ cityWeatherCollection, loading, rerender }) =>{/* 一些使用效果被跳过 *//* 跳过了一些事件处理程序 */const 列 = React.useMemo(() => [{标题:'城市',单元格:({名称,标题}:EnhancedCityWeather)=><Link to={`/${name}`} className=city">{title}</Link>},{标题:'温度',单元格:({温度}:EnhancedCityWeather)=>(<div className="温度"><span className=摄氏度">{`${温度}°C`}</span><span className=fahrenheit">{` (~${Math.round(temperature * (9/5)) + 32}°F)`}</span>

)},{标题:'',单元格:({ isFavorite } : EnhancedCityWeather) =>isFavorite &&(<心形图标填充=#6d3fdf";高度={20}宽度={20}/>),},], []);返回 (<表格列={columns} items={sortedItems} loading={loading}/>);};

现在,我写了一些这样的测试:

jest.mock('../../../components/Table', () => ({__esModule: 真,默认值:jest.fn(() => 

),}));让 cityWeatherCollection: EnhancedCityWeather[];让加载:布尔值;让重新渲染:() =>{};beforeEach(() => {cityWeatherCollection = [/*...一些对象...*/];加载 = 真;rerender = jest.fn();使成为(<浏览器路由器><天气报告cityWeatherCollection={cityWeatherCollection}加载={加载}重新渲染={重新渲染}/></BrowserRouter>);});it('渲染表格', () => {期望(screen.queryByTestId('Table')).toBeInTheDocument();});it('将加载道具传递给 Table', () => {期望(表).toHaveBeenCalledWith(expect.objectContaining({loading }),期望.任何事情(),);});it('按 isFavorite 然后按字母顺序排序后将 items prop 传递给 Table', () => {期望(表).toHaveBeenCalledWith(期望.objectContaining({项目: cityWeatherCollection.sort((item1, item2) => (+item2.isFavorite - +item1.isFavorite||item1.name.localeCompare(item2.name))),}),期望.任何事情(),);});

如果您检查我的组件,它有一个名为 columns 的变量.我正在将该变量分配给 Table 组件.

我认为,我应该测试列是否作为道具传递给 Table 组件.我想对了吗?如果是这样,请告诉我如何为此编写测试用例?

此外,如果您能建议我如何测试在列属性中声明的每个单元格,那将会很有帮助.

解决方案

不建议使用 React 测试库测试实现细节,例如组件 props.相反,您应该在屏幕内容上进行断言.


推荐

expect(await screen.findByText('some city')).toBeInTheDocument();期望(screen.queryByText('过滤掉城市')).not.toBeInTheDocument();


不推荐

如果你无论如何都想测试道具,你可以试试下面的示例代码.来源

从'./Table'导入表jest.mock('./Table', () => jest.fn(() => null))//... 在你的测试中期望(表).toHaveBeenCalledWith(道具,上下文)

您可能主要在以下两种情况下考虑使用这种方法.

您已经尝试了推荐的方法,但您注意到组件是:

  1. 使用遗留代码,因此它使测试变得非常困难.重构组件也会花费太长时间或风险太大.
  2. 非常慢,并且会大大增加测试时间.该组件也已经在其他地方进行了测试.

看看一个非常相似的问题这里

My component looks something like this: (It has more functionality as well as columns, but I have not included that to make the example simpler)

const WeatherReport: FunctionComponent<Props> = ({ cityWeatherCollection, loading, rerender }) => {
  /* some use effects skipped */
  /* some event handlers skipped */

  const columns = React.useMemo(() => [
    {
      header: 'City',
      cell: ({ name, title }: EnhancedCityWeather) => <Link to={`/${name}`} className="city">{title}</Link>
    },
    {
      header: 'Temp',
      cell: ({ temperature }: EnhancedCityWeather) => (
        <div className="temperature">
          <span className="celcius">{`${temperature}°C`}</span>
          <span className="fahrenheit">{` (~${Math.round(temperature * (9 / 5)) + 32}°F)`}</span>
        </div>
      )
    },
    {
      header: '',
      cell: ({ isFavorite } : EnhancedCityWeather) => isFavorite && (
        <HeartIcon
          fill="#6d3fdf"
          height={20}
          width={20}
        />
      ),
    },
  ], []);

  return (
    <Table columns={columns} items={sortedItems} loading={loading} />
  );
};

Now, I wrote some tests like this:

jest.mock('../../../components/Table', () => ({
  __esModule: true,
  default: jest.fn(() => <div data-testid="Table" />),
}));

let cityWeatherCollection: EnhancedCityWeather[];
let loading: boolean;
let rerender: () => {};

beforeEach(() => {
  cityWeatherCollection = [/*...some objects...*/];

  loading = true;
  rerender = jest.fn();

  render(
    <BrowserRouter>
      <WeatherReport
        cityWeatherCollection={cityWeatherCollection}
        loading={loading}
        rerender={rerender}
      />
    </BrowserRouter>
  );
});

it('renders a Table', () => {
  expect(screen.queryByTestId('Table')).toBeInTheDocument();
});

it('passes loading prop to Table', () => {
  expect(Table).toHaveBeenCalledWith(
    expect.objectContaining({ loading }),
    expect.anything(),
  );
});

it('passes items prop to Table after sorting by isFavorite and then alphabetically', () => {
  expect(Table).toHaveBeenCalledWith(
    expect.objectContaining({
      items: cityWeatherCollection.sort((item1, item2) => (
        +item2.isFavorite - +item1.isFavorite
        || item1.name.localeCompare(item2.name)
      )),
    }),
    expect.anything(),
  );
});

If you check my component, it has a variable called columns. I am assigning that variable to Table component.

I think, I should test that columns are being passed as props to the Table component. Am I thinking right? If so, can you please tell me how can I write a test case for that?

Also, it will be helpful if you can suggest me how can i test each cell declared inside columns property.

解决方案

It is not recommended to test implementation details, such as component props, with React Testing Library. Instead you should be asserting on the screen content.


Recommended

expect(await screen.findByText('some city')).toBeInTheDocument();
expect(screen.queryByText('filtered out city')).not.toBeInTheDocument();


Not Recommended

If you want to test props anyways, you can try the sample code below. Source

import Table from './Table'
jest.mock('./Table', () => jest.fn(() => null))

// ... in your test
expect(Table).toHaveBeenCalledWith(props, context)

You might consider this approach mainly on the two following scenarios.

You already tried the recommended approach but you noticed the component is:

  1. using legacy code and because of that it makes testing very hard. Refactoring the component would also take too long or be too risky.
  2. is very slow and it drastically increases the testing time. The component is also already tested somewhere else.

have a look at a very similar question here

这篇关于如何测试道具是否传递给孩子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆