0

我正在测试连接到 redux 存储的 React 组件中函数的执行。我只能监视一些函数,其余的全部返回:无法监视 setEmail(或其他函数名称)属性,因为它不是函数;给定的未定义

在下面的代码中,我添加了箭头,指出哪些是可监视的,当我 console.log(BaseForm.WrappedComponent.prototype.functionName) 那些不可监视的返回未定义时。可以窥探的返回[功能:...]我真的不明白为什么?

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

    this.state = {
      ages: [],
    };
  }

  componentDidMount() {
    this.createAges(); <----- can spy on this one as it is a function
  }

  setEmail = (elemName, value) => { <------ Cannot spy the setEmail property because it is not a function; undefined
    this.setState({ email: value });
    this.props.saveEmail(value);
  };

  handleEmailSignup = (e) => { <-------- Cannot spy the setEmail property because it is not a function; undefined
    this.setState({ offersSignup: e.target.checked });
  };

  onChangeAge = (e) => { <------ Cannot spy the setEmail property because it is not a function; undefined
    this.setState({
      selectedAge: e.target.value,
      selectedAgeIndex: e.target.index - 1,
      errorAge: '',
    });
  };

  createAges() { <------ can spyOn as it is a function
    let ages = [
      { value: '', text: !__isEmpty(sessionStorage.getItem('gf')) ? 'Kid age' : 'Your age' },
      { value: '14 and younger', text: '14 and younger' },
      { value: '15', text: '15' },
      { value: '16', text: '16' },
      { value: '17', text: '17' },
    ];

    this.setState({ ages: ages });
  }

  render() {
    return (
      <div>
        <div data-type="email" className="textbox-wrapper">
          <Textbox
            type="email"
            placeholder="Email Address"
            name="register-email"
            onChange={this.setEmail}
            onBlur={this.checkUserByEmail}
            defaultValue={this.state.email} <------- in test the value does not change, but on UI it does and functions well
            isError={!__isEmpty(this.props.emailErrorClass)}
          />
        </div>

        <Dropdown options={this.state.ages} onChange={this.onChangeAge} selectedValue={this.state.selectedAge} />

        <div>
          <input name="offersSignup" type="checkbox" onChange={this.handleEmailSignup} checked={this.state.offersSignup} />
        </div>
      </div>
    );
  }
}

const mapDispatchToProps = { saveEmail };

export default connect(null, mapDispatchToProps)(BaseForm);

it.only('set email in local state if onChange of Textbox is fired', () => {
    //console.log(BasePartnerRegistrationForm.WrappedComponent.prototype.setEmail);
    // above is undefined
    const setEmailSpy = jest.spyOn(BaseForm.WrappedComponent.prototype, 'setEmail');
    const wrapper = mount(
      <Provider store={store}>
        <BaseForm {...baseProps} />
      </Provider>
    );

    const event = { target: { value: 'event value' } };
    wrapper.find('Textbox').at(0).simulate('change', event);
    wrapper.update();
    expect(setEmailSpy).toHaveBeenCalled();
    // below shows unchanged email value in state
    // expect(wrapper.find('Textbox').at(0).props().defaultValue).toBe(event.target.value);
  });

下面尝试了一种新方法,控制台错误:预期:“事件值”接收:“”换句话说,每个测试用例,setState 不起作用,但它在 UI 和 chrome 控制台上也能正常工作。

it('set email in local state if onChange of Textbox is fired', async () => {
    const wrapper = mount(
      <Provider store={store}>
        <BasePartnerRegistrationForm {...baseProps} />
      </Provider>
    );

    const event = { target: { value: 'event value' } };
    wrapper.find('Textbox').at(0).simulate('change', event);
    await waitFor(() => expect(wrapper.find('Textbox').at(0).props().defaultValue).toBe(event.target.value));
  });
4

1 回答 1

0

与其监视方法调用,不如检查 DOM。首先,我建议您查看React 测试库以查找字段、设置值、查询 DOM 以进行更改。这与 Jest 一起是 React 测试中的新标准(甚至包含在 React-Create-App 中)。这是一种范式转变,使用测试用户交互和结果(就像用户一样),它正在测试底层逻辑。

接下来要考虑的是时机。当您设置状态时,它不是立即的。渲染状态更改需要几毫秒。RTL 提供了waitFor一种进一步简化此过程的方法。

waitFor(() => /*some assertion*/);
于 2022-01-25T20:24:10.203 回答