我需要先说清楚一件事:
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);
});
const submit = () => console.log('submit clicked');
位于Home
函数内部,这使它成为一个封闭作用域不可访问的函数。首先,你应该尝试将其移出函数之外,然后可能可以导出该函数,然后在测试中导入它,附加一个 spy 并查看是否被调用。 - Rikin