【问题标题】:Cannot spyOn on a primitive value; undefined given - Testing a function execution in onChange in connected component无法窥探原始值; undefined given - 在连接组件的 onChange 中测试函数执行
【发布时间】:2022-01-21 10:39:32
【问题描述】:

测试新手,这是一个使用 redux 的连接组件。我正在测试是否调用了 maskPromoCode 函数。使用当前的测试代码,错误提示:无法对原始值进行监视;给定的未定义

不明白为什么。谢谢。

组件:

class Textbox extends React.Component {
  constructor(props) {
      super(props);
  }

 onChange(e) {
    e.preventDefault();
    this.setState({
      value: this.maskPromoCode(e.target.value) 
    })
 }

  maskPromoCode(value) {...}

  render() {
    return (
      <>
        <input
          ...
          onChange={e => this.onChange(e)} 
        />  
      </>
    );
  }
}
const mapDispatchToProps = { setError, setPwError };
export default connect(null, mapDispatchToProps)(Textbox);

测试文件

it('invokes the maskPromoCode function with event value', () => {
    const funcMock = jest.spyOn(Textbox.prototype, 'maskPromoCode');
    
    const wrapper = mount(
      <Provider store={store}>
        <Textbox {...baseProps} name="redeem-promo" />
      </Provider>
    );

    const inputField = wrapper.find('input');
    const event = {
      target: {
        value: 'event value',
      },
    };
    inputField.simulate('change', event);
    expect(funcMock).toHaveBeenCalledWith(event.target.value);
  });

【问题讨论】:

    标签: reactjs unit-testing redux jestjs enzyme


    【解决方案1】:
    1. Textbox 组件被connect 函数包裹,它变成了一个没有prototype 的HOC,我猜你在测试文件中导入了HOC。测试文件中导入的TextBox 组件是一个HOC。所以TextBox.prototypeundefined,这就是jest.spyOn 抛出错误的原因。

    2. 如果您坚持使用jest.spyOn() 作为maskPromoCode 方法,您可以使用jest.spyOn(Textbox.WrappedComponent.prototype, 'maskPromoCode')。 HOC上有一个WrappedComponent静态属性,可以获取到原来的组件类。

    3. 建议:如果使用jest.spyOn(...),您正在测试实现细节,您应该测试组件行为。

    例如

    Textbox.jsx:

    import React from 'react';
    import { connect } from 'react-redux';
    
    class Textbox extends React.Component {
      constructor(props) {
        super(props);
        this.state = { value: '131' };
      }
    
      onChange(e) {
        e.preventDefault();
        this.setState({ value: this.maskPromoCode(e.target.value) });
      }
    
      maskPromoCode(value) {
        return '***';
      }
    
      render() {
        return (
          <>
            <input value={this.state.value} onChange={(e) => this.onChange(e)} />
          </>
        );
      }
    }
    export default connect(null, null)(Textbox);
    

    Textbox.test.jsx:

    import Textbox from './Textbox';
    import React from 'react';
    import configureStore from 'redux-mock-store';
    import { Provider } from 'react-redux';
    
    describe('70795348', () => {
      it('invokes the maskPromoCode function with event value', () => {
        console.log(Textbox.WrappedComponent.prototype.maskPromoCode);
        const mockStore = configureStore();
        const store = mockStore();
        const wrapper = mount(
          <Provider store={store}>
            <Textbox name="redeem-promo" />
          </Provider>
        );
        expect(wrapper.find('input').instance().value).toBe('131');
        const event = { target: { value: 'event value' } };
        wrapper.find('input').simulate('change', event);
        expect(wrapper.find('input').instance().value).toBe('***');
      });
    });
    

    测试结果:

     PASS  stackoverflow/70795348/Textbox.test.jsx
      70795348
        ✓ invokes the maskPromoCode function with event value (40 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        2.729 s, estimated 9 s
    

    【讨论】:

    • Hiiiiii 非常感谢你救了我的命
    • @DollyBabe 你现在有
    • 哇,我是如何在一分钟内从 13 点到 25 点的!!! :D
    • 您好,有时间可以看看stackoverflow.com/questions/70781960/… 似乎没有人回答...谢谢
    猜你喜欢
    • 2020-02-24
    • 2021-11-02
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多