如何测试一个组件是否以另一个组件作为参数调用函数 prop?

How to test that a component calls a function prop with another component as argument?

我有一个组件接收一个函数作为 prop 并将渲染的元素传递给它,挂载:

function MyComponent(props) {
  useEffect(() => {
    props.onHeaderChange(<button>Back</button>)
  }, [])

  return (<div>My Component</div>)
}

我想编写一个测试来检查后退按钮是否通过:

test("it renders the back button", () => {
  const onHeaderChange = jest.fn()
  const { getByText } = render(
    <MyComponent {...props} onHeaderChange={onHeaderChange} />
  )

  expect(onHeaderChange).toHaveBeenCalledWith("How to test for the back button here?")
})

但我不确定 jest / react 测试库语法是什么?

有两种解决方法:

选项 1. 将 JSX 传递给 toHaveBeenCalledWith 方法就足够了。为什么?因为 JSX 是 React.createElement() 方法的语法糖。使用 JSX 编写的代码将转换为使用 React.createElement()。它的 return 值只是一个 JavaScript 对象。

index.tsx:

import React, { useEffect } from 'react';

export function MyComponent(props) {
  useEffect(() => {
    props.onHeaderChange(<button>Back</button>);
  }, []);

  return <div>My Component</div>;
}

index.test.tsx:

import { render } from '@testing-library/react';
import React from 'react';
import { MyComponent } from '.';

describe('71995270', () => {
  test('it renders the back button', () => {
    const onHeaderChange = jest.fn();
    render(<MyComponent onHeaderChange={onHeaderChange} />);

    const expectedElement = React.createElement('button', null, 'Back');
    console.log('expectedElement: ', expectedElement);
    expect(onHeaderChange).toHaveBeenCalledWith(expectedElement);
    expect(onHeaderChange).toHaveBeenCalledWith(<button>Back</button>);
  });
});
 PASS  Whosebug/71995270/index.test.tsx (14.782 s)
  71995270
    ✓ it renders the back button (42 ms)

  console.log
    expectedElement:  {
      '$$typeof': Symbol(react.element),
      type: 'button',
      key: null,
      ref: null,
      props: { children: 'Back' },
      _owner: null,
      _store: {}
    }

      at Object.<anonymous> (Whosebug/71995270/index.test.tsx:11:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        16.871 s

选项 2. 使用 mockImplementation 模拟 onHeaderChange 函数并获取测试用例中的 button 元素,render它并断言。

test('it renders the back button - 2', () => {
  let buttonElement;
  const onHeaderChange = jest.fn().mockImplementation((element) => {
    buttonElement = element;
  });
  render(<MyComponent onHeaderChange={onHeaderChange} />);

  const { getByRole } = render(buttonElement);
  expect(getByRole('button')).toHaveTextContent('Back');
});