【问题标题】:Material-UI TextField onChange doesn't invoke function in a testMaterial-UI TextField onChange 不会在测试中调用函数
【发布时间】:2021-02-11 05:55:28
【问题描述】:

我正在学习 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

这里有什么不明白的地方?

【问题讨论】:

    标签: reactjs jestjs material-ui react-testing-library


    【解决方案1】:

    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) 匹配器来断言该函数被调用了多少次。

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

    请参阅Which query should I use? 以了解有关 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);
    

    【讨论】:

    • 太棒了。有用。谢谢。如果您不介意,我确实有一个评论和一个问题。首先,我在代码中有 configure({ testIdAttribute: 'id' }); 语句,因为据我了解 TextField 不采用 testId 属性。我保留了id 属性并且测试仍然有效。至于我的问题,我理解您所说的使用getByRole 的内容,但是当在TextField 中属性为text="password 时,我遇到了问题,因为输入密码类型然后似乎没有相应的角色。那我该怎么办?还有,如果有2_箱怎么办?
    • 抱歉,我在阅读您的问题时错过了configure 的详细信息。是的,您是对的,您不能将data-testid 直接传递给TextField,您需要将其传递给inputProps.data-testid。有关更多详细信息,请参阅this 演示。 @user2921009
    • 关于申请哪个角色,你可以看到完整的有效角色列表here,如果你的元素没有合适的角色,回退到getByLabelText()或者getByPlaceholderText() priority list。 @user2921009
    • 您还可以在这个互动式playground 中玩转,以发现应该将哪些查询应用于您的元素@user2921009
    猜你喜欢
    • 2020-11-28
    • 2019-02-25
    • 1970-01-01
    • 2020-05-03
    • 2021-02-18
    • 2020-03-22
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多