如何测试期望e:React.ChangeEvent <htmlinputelement>作为参数的函数?

时间:2018-09-14 01:08:57

标签: reactjs unit-testing jestjs

如何在不创建完整的doStuff对象的情况下对下面的React.ChangeEvent方法进行单元测试?

// my-form.tsx
export const doStuff = (changeHandler: ChangeHandler, e: React.ChangeEvent<HTMLInputElement>) => {
  // A call to another function takes place here, but for brevity, I'm using console.log
  console.log(e); 
  changeHandler(e);
}

interface ChangeHandler {
  (e: React.ChangeEvent<HTMLInputElement>): void;
}

interface MyFormProps {
  changeHandler: ChangeHandler,
  username: string;
  password: string;
}

const MyForm: React.SFC<MyFormProps> = ({changeHandler, username, password}) => (
  <form>
    <div>
      <label htmlFor="username">Username</label>
      <input
        type="text"
        name="username"
        value={username}
        onChange={doStuff.bind(null, changeHandler)} />
    </div>
    <div>
      <label htmlFor="password">Password</label>
      <input
        type="text"
        name="password"
        value={password}
        onChange={doStuff.bind(null, changeHandler)} />
    </div>
    <button>Submit</button>
  </form>
);

export default MyForm;

下面是我的测试文件。为了测试doStuff,我要做的是第一个测试。我认为第二项测试就是我也可以测试doStuff的方法。

// my-form.test.tsx
import MyForm, { doStuff } from './my-form.tsx';

describe('MyForm' => {
  it('should call the changeHandler', () => {
    // Arrange
    const changeHandlerMock = jest.fn();

    // Act
    // How can I pass a mock for the 2nd parameter?
    // doStuff(changeHandlerMock, {});

    // Assert
    expect(changeHandlerMock.called.length).toEqual(1);
  });

  it('should call the changeHandler too', () => {
    // Arrange
    const changeHandlerMock = jest.fn();

    // Act
    const wrapper = shallow(
      <MyForm
        changeHandler={changeHandlerMock}
        username={username}
        password={password} />
    );
    wrapper.find(`input[name='username']`).simulate('change');

    // Assert
    expect(changeHandlerMock.called.length).toEqual(1);
  })
});

或者,我可以摆脱doStuff并将每个输入元素的标记更改为:

onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
  console.log(e);
  changeHandler(e);
}} />

缺点是,如果需要更改eventHandler,则必须在声明的每个位置进行更改,因此需要使用doStuff方法。

为完整起见,这是我的容器组件:

interface MyFormContainerState {
  username: string;
  password: string;
}

// my-form-container.tsx
class MyFormContainer extends React.Component<{}, MyFormContainerState> {
  constructor(props: {}) {
    super(props);

    this.state = {
      username: '',
      password: ''
    };
  }

  public render() {
    const { username, password } = this.state;

    return (
      <MyForm
        changeHandler={this.changeHandler}
        username={username}
        password={password} />
    );

  }

  public changeHandler = (e: React.ChangeEvent<HTMLInputElement>): void => {
    this.setState({
      ...this.state,
      [e.currentTarget.name]: e.currentTarget.value
    });
  }
}

0 个答案:

没有答案