React测试库:检查组件方法是否被调用

3

使用 '@testing-library/react' 库,

假设有以下组件:

const Home = () => {
   const submit = () => console.log('submit clicked');

   return (
     <div>
       Home
      <Button
        onClick={submit}
      >
        Submit
      </Button>
     </div>
   )
}

在下面的测试中,需要添加什么断言才能完成测试?

it('reacts to a submit event', async () => {
    const { getByText } = render(<Home />);

    fireEvent.click(getByText(/submit/i));
  })

2
你的 const submit = () => console.log('submit clicked'); 位于 Home 函数内部,这使它成为一个封闭作用域不可访问的函数。首先,你应该尝试将其移出函数之外,然后可能可以导出该函数,然后在测试中导入它,附加一个 spy 并查看是否被调用。 - Rikin
4
或者你可以检查一些DOM文本的变化,以确定点击是否成功。 - Rikin
2
我同意@Rikin的观点,不要检查方法是否被调用。当它被调用时,会发生一些事情并且页面会改变。只需检查这些变化是否发生即可。 - Gio Polvara
1个回答

1
我需要先说清楚一件事:Testing Library's Guiding Principles认为测试实现细节,比如断言特定的内部函数是否被调用,是一种不好的模式:
引用: 你的测试越像你的软件使用方式,它们给予你的信心就越多。
按照目前的写法,你的组件的submit函数是一个实现细节。消费者并不知道提交按钮是如何实现的,但他们可以期望按钮被渲染并且可点击。只是没有指示应该发生什么。
我更喜欢在DOM上断言按钮点击的效果,但如果只能记录到控制台,你可以对console.log进行监视:
test('logs something to the console when submit is clicked', () => {
  const spy = jest.spyOn(console, 'log');
  render(<Home />);
  
  const submitButton = screen.getByRole('button', { name: /submit/i });
  fireEvent.click(submitButton);

  expect(spy ).toHaveBeenCalledWith('submit clicked');
});

所以,我们可以这样做,但我真的强烈建议你考虑一下我们是否应该这样做。这真的感觉像是测试实现细节,这会导致脆弱的测试。脆弱的测试往往在实现细节发生变化时会出错。当用户体验没有改变而测试却失败时,这表明测试是毫无价值的。一个好的测试应该能够让你对软件是否按照用户的期望工作有信心。
当然,这并不意味着你不应该测试组件的API。如果你的组件被调整为接受一个函数,在点击“提交”按钮时调用该函数,那么使用模拟渲染它、模拟按钮点击,并断言它按照消费者的期望工作是可以的:
test('calls the provided submit function', () => {
  const submit = jest.fn();
  render(<Home submit={submit} />);
  
  const submitButton = screen.getByRole('button', { name: /submit/i });
  fireEvent.click(submitButton);

  expect(submit).toHaveBeenCalledTimes(1);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接