首页 > 解决方案 > 无法用浅层和酶测试 onChange 模拟方法

问题描述

我无法解决 onChange 测试,也解决了 onClick 的问题,但以某种方式成功解决了它。
我已经关注了 Enzyme 和 Jest 的文档,但它没有用,在 Pluralsight 上学习了 2 门课程,但结果是一样的,在这里阅读了许多文章和解决方案,但它不会通过。我发现了 .simulate() 的弃用并尝试了 props.onChange。

我会很高兴得到任何帮助。

这是我要测试的组件:

    const [details, setdetails] = useState(
        {
            fullName: '',
            email: '',
            phone: ''
        }
    )
    const [errors, setErrors] = useState({});
    const [isValid, setValid] = useState(false);

    const handleChange = event => {
        let { name, value } = event.target;
        console.log(value, name, event.target);
        event.preventDefault();
        setdetails(prevDetails => ({
            ...prevDetails,
            [name]: value
        }));

    }
   return (
        <div className="contact" id="contact">
            <div className="logo"></div>
            <div className="contact-title">
                <h6>PLEASE LEAVE YOUR DETAILS BELOW AND WE’LL CONTACT YOU</h6>
            </div>
            <div className="fields">
                <form>
                    <div className="input-field">
                       <label>Full Name:</label>
                       <input name="fullName" placeholder="Full Name" onChange={handleChange}
                   />
                       <div className="text-danger">{errors.fullName}</div>
                  </div>
                  <div className="input-field">
                    <label>Email:</label>
                    <input name="email" placeholder="Email" onChange={handleChange} 
                  />
                    <div className="text-danger">{errors.email}</div></div>
                 <div className="input-field">
                     <label>Phone:</label> 
                     <input name="phone" placeholder="Phone Number" onChange={handleChange} 
                 />
                     <div className="text-danger">{errors.phone}</div>
                </div>
                <div>
                        <button type="submmit" 
                          className="btn-dark button"
                          onClick={handleClick}
                        >Submit</button>
                </div>
             </form>
            </div>
        </div>
    )

测试尝试:

describe('', () => {
    it('', () => {
        let mockOnChange = jest.fn();
        const props = {
            mockOnChange: mockOnChange
        }
        let wrapper = shallow(<Contact {...props} />)
        console.log(wrapper.debug());
        let event = {
            preventDefault: () => { },
            name: 'fullName',
            target: {
                value: 'test'
            }

        }
        wrapper.find('input').at(0).props().onChange({ event })
        expect(mockOnChange).toHaveBeenCalledWith('test');
    })
    it('second assertion', () => {
        let mockOnChange = jest.fn();
        let name = 'fullName';
        let value = 'test';
        let wrapper = shallow(<Contact onChange={mockOnChange} />)
        console.warn(mockOnChange);
        wrapper.instance().onChange({ target: { name, value } });
        expect(mockOnChange).toHaveBeenCalled('test');
    })
    it('', () => {
        let handleChange = jest.fn();
        let mockName = 'fullName';
        let mockValue = 'test';
        let wrapper;
        wrapper = shallow(<Contact onChange={handleChange} />);
        wrapper.find('input').at(0).simulate('change', {
            preventDefault: () => { },
            target: {
                name: mockName,
                value: mockValue
            }
        })
        expect(handleChange).toHaveBeenCalledWith("test");

    })
})


describe("simulate onchange input fileds", () => {
    let wrapper;
    let mockOnChange;
    beforeEach(() => {
        mockOnChange = jest.fn();
        const props = {
            mockOnChange: mockOnChange
        }
        wrapper = shallow(<Contact {...props} />);
    });
    it('first assertion', () => {

        wrapper.find('input').at(0).simulate('change', {
            preventDefault: () => { },
            target: { value: 'test' }
        })
        expect(mockOnChange).toBeCalledWith("test");
    })

    it('should call onChange prop', () => {
        const event = {
            preventDefault: () => { },
            target: {
                name: 'fullName',
                value: 'test'
            }
        };
        const component = shallow(<Contact onChange={mockOnChange} />);
        component.find('input').at(0).props().onChange('change', event);
        expect(mockOnChange).toBeCalledWith('test');
    });
})

标签: reactjsjestjsenzyme

解决方案


您的组件不调用props.mockOnChangeprops.handleChange类似。它只是从事件中获取新值,将其存储在其状态中并将其呈现为适当输入的值。

此外,目前您的组件根本不details用于渲染。我希望它看起来像

<input 
  name="fullName" 
  placeholder="Full Name" 
  onChange={handleChange}
  value={details.fullName}
/>

然后我们将能够验证这种行为(还要注意event' 的结构,在您的代码中,您要在子对象name之外设置属性target):

it('', () => {
    let wrapper = shallow(<Contact {...props} />)
    let event = {
        preventDefault: jest.fn(),
        target: {
            name: 'fullName',
            value: 'test'
        }

    }
    wrapper.find('input[name="fullName"]').simulate('change', event)
    expect(wrapper.find('input[name="fullName"]').prop('value')).toBe('test');
    expect(wrapper.find('input[name="email"]').prop('value')).toBe('');
    expect(event.preventDefault).toHaveBeenCalled();

推荐阅读