首页 > 解决方案 > Material-UI TextField onChange 不会在测试中调用函数

问题描述

我正在学习 Jest 和 React 并尝试使用 Material-UI。我写了这个简单的测试只是为了检查事情是如何工作的:

import React from 'react';
import { render, fireEvent, configure} from '@testing-library/react';

import { TextField } from '@material-ui/core';

configure({ testIdAddribute: 'id' });

describe('Testing events', () => {

  test('onChange', () => {
    const onChangeMock = jest.fn();
    
    const { getByTestId } = render(
      <TextField id="test" onChange={onChangeMock} type="text" />
    );
    
    fireEvent.change(getByTestId('test', { target: { value: 'foo' } }));
    expect(onChangeMock.mock.calls.length).toBe(1);
  });
});

但是这个测试失败了:

expect(received).toBe(expected) // Object.is equality

    Expected: 1
    Received: 0

我在这里不明白什么?

标签: reactjsjestjsmaterial-uireact-testing-library

解决方案


getByTestId()将寻找data-testid属性,而不是id. 尝试更改您的代码

<TextField id="test" onChange={onChangeMock} />

<TextField inputProps={{ data-testid="test" }} onChange={onChangeMock} />

现在在你的代码中

fireEvent.change(getByTestId('test', { target: { value: 'foo' }}));
expect(onChangeMock.mock.calls.length).toBe(1);

在模拟用户的按键操作时,您应该使用@testing-library/user-event并调用而不是自己手动user.type()触发事件。onChange

您还可以使用.toHaveBeenCalledTimes(number)matcher 来断言该函数被调用了多少次。

最后,您应该使用getByRole()而不是,getByTestId()因为用户将看到TextField( getByRole('textbox')) 而不是data-testid元素的属性,您只能在检查元素时看到该属性。

请参阅我应该使用哪个查询?了解更多关于 RTL 的哲学。

把它放在一起,你会得到这样的东西:

import { screen } from '@testing-library/dom'
import user from '@testing-library/user-event'

...

const onChangeMock = jest.fn();
    
render(<TextField onChange={onChangeMock} />);

const input = screen.getByRole('textbox')

user.type(input, 'foo')
expect(onChangeMock).toHaveBeenCalledTimes(3);

推荐阅读