Jest.js 在使用react-testing-library时,如何测试组件是否使用正确的 prop 呈现?

r7knjye2  于 2022-12-08  发布在  Jest
关注(0)|答案(4)|浏览(244)

我有一些组件正在呈现另一个组件(FetchNextPageButton),该组件已经过单独测试,例如:

const News = () => (
  <div>
    <h1>News</h1>
    ...
    <FetchNextPageButton query={NEWS_QUERY} path="viewer.news" />
  </div>
)

const Jobs = () => (
  <div>
    <h1>Jobs</h1>
    ...
    <FetchNextPageButton query={JOBS_QUERY} path="viewer.jobs" />
  </div>
)

const Posts = () => (
  <div>
    <h1>Posts</h1>
    ...
    <FetchNextPageButton query={POSTS_QUERY} path="viewer.posts" />
  </div>
)

问题是,我不想为已经在其他地方测试过的功能在每个组件上添加测试,所以我认为这应该足以测试组件是否被呈现以及我是否向它传递了正确的属性。
我可以很容易地用Enzyme来测试这个问题:

expect(wrapper.find('FetchNextPageButton').props()).toMatchObject({
  query: NEWS_QUERY,
  path: "viewer.news"
})

因此,我想知道使用React testing library来测试它的最佳方法是什么。

gjmwrych

gjmwrych1#

这是肯特C. Dodds(RTL的创建者)与我讨论后分享的方法:

import FetchNextPageButton from 'FetchNextPageButton'

jest.mock('FetchNextPageButton', () => {
  return jest.fn(() => null)
})

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

wkyowqbh2#

不要相信这是可能的。RTL看起来像是专注于对DOM而不是React的组件树进行验证。
我看到的唯一解决方法是模拟FetchNextPageButton,使其将所有 prop 渲染为属性。

jest.mock("../../../FetchNextPageButton.js", () => 
  (props) => <div data-test-id="FetchNextPageButton" {...props} />);
....
const { getByTestId } = render(<YourComponent />);
expect(getByTestId("FetchNextPageButton")).toHaveAttribute("query", NEWS_QUERY);
expect(getByTestId("FetchNextPageButton")).toHaveAttribute("path", "viewer.news");

当然,这只适用于 prop 中的原始值,但验证对象或函数之类的东西会更难。
想想看,这不是RTL方式,但我同意在每个容器的范围内检查这一点将是大量的工作(完全忽略这一点将是一种风险)。
PS toHaveAttribute来自jest-dom

v1l68za4

v1l68za43#

在我的例子中,我想测试高阶分量(HOC),正确地增强传递到HOC的分量。
我需要做的是,使实际的组件成为一个mock,并将其传递给HOC。就像现有答案中所描述的那样,您可以只期待HOC添加的属性。

// after 'Component' get's passed into withSelectionConstraint, it should have an id prop
const Component = jest.fn(() => <h1>Tag Zam</h1>);
const WithConstraint = withSelectionConstraint(Component, ["instance"], true);
render(<WithConstraint />);

// passing the jest mock to the HOC, enables asserting the actual properties passed by the HOC
expect(Component).toHaveBeenCalledWith(
    expect.objectContaining({ ids: mockInstanceRows.map(x => x.id) }), 
    expect.anything()
)
sg24os4d

sg24os4d4#

根据Ben的回答,我写了一个不会引起任何错误的版本:

jest.mock(
  'path/to/your/component',
  () => {
    const MockedComponent = (props: any) => {
      const cleanedProps = Object.keys(props).reduce<Record<string, unknown>>(
        (a, b) => {
          // Needed because html attributes cannot be camel cased
          a[b.toLowerCase()] = props[b].toString();
          return a;
        },
        {}
      );

      return (
        <div data-testid="any-test-id" {...cleanedProps} />
      );
    };

    return MockedComponent;
  }
);

请注意,属性值(expect(getByTestId('any-test-id')).toHaveAttribute('attribute','value'))将被字符串化。

相关问题