如何在ReactJS组件单元测试中“模拟”状态值?

bie*_*ier 5 unit-testing reactjs redux

我正在尝试对我的ReactJS组件进行单元测试。基本上,它是一个由输入和按钮组成的简单组件。当单击按钮时,它会触发一个名为“ onSave”的事件,并且仅在state.textValue不为空时才调用“ this.props.addTodo”:

import React, {Component, PropTypes} from 'react';

export default class Invoer extends Component {

    static propTypes = {
        saveTodo: PropTypes.func.isRequired
    }

    constructor(props) {
        super();
        this.props = props;
        this.state = {textValue: ''};
    }


    onChange = (event) => {
        if (event.target.value !== '') {
            this.setState({textValue: event.target.value});
            console.log(event.target.value);
        }
    }

    onSave = () => {
        if (this.state.textValue!== '') {
            this.props.saveTodo(this.state.textValue);
        }
    }

    render() {
        return (
            <header>
                <input type="text" value={this.state.textValue} onChange={this.onChange}/>
                <button onClick={this.onSave}>save</button>
            </header>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

我为onSave事件编写了一个单元测试。唯一的问题是,我无法弄清楚如何“模拟” this.state.textValue以便在第26行上设置状态,请参见上文:

import React from 'react';
import Invoer from "../components/Invoer";
import {createRenderer} from 'react-test-renderer/shallow';
it('should call this.props.saveTodo event when clicking on button on non empty value', () => {
    const props = {
        saveTodo: jest.fn()
    }

    const renderer = createRenderer();
    renderer.render(<Invoer {...props} />)
    const output = renderer.getRenderOutput()

    //tried to mock the state.textValue, results in error:
    //output.props.children[0].value = 'hoera';

    output.props.children[1].props.onClick();

    expect(props.saveTodo).toBeCalled()
});
Run Code Online (Sandbox Code Playgroud)

运行此测试时,出现此错误:

should call this.props.saveTodo event when clicking on button on non empty value
    expect(jest.fn()).toBeCalled()    
    Expected mock function to have been called.
Run Code Online (Sandbox Code Playgroud)

当然是预期的。我如何“模拟” this.state.textValue?还是这完全是错误的方法?

bli*_*ish 7

对于遇到这个问题的其他人(我假设OP现在已经解决了这个问题) - 如果使用,您可以直接在组件上调用setState:

// assuming props and mockState are set in a beforeEach()
it('adds state to the component', () => {
  const myComponent = shallow(<MyComponent {...props} />);
  myComponent.setState({ ...mockState });
  const instance = myComponent.instance();
  expect(instance.state).toEqual(mockState);

  // you can then directly call instance methods - e.g. mocking 
  // previous props/state to test changes are handled as expected
  instance.componentDidUpdate(prevProps, prevMockState);
});
Run Code Online (Sandbox Code Playgroud)

请注意,根据您的要求,您可能需要使用mount()而不是shallow().

  • 不使用酶吗?只是开玩笑 (4认同)
  • 同样 - 我没有服用酶。有什么玩笑推荐吗? (3认同)
  • 撞。有人有 Jest 的解决方案吗?如果找到的话会更新。 (2认同)