测试反应函数用Jest调用

时间:2016-03-25 18:50:26

标签: javascript unit-testing reactjs jestjs

我有一个React类,它呈现一个名为PersonalDetails的子组件。代码工作正常,但是当在字段中按Enter键时,我无法让Jest验证是否正确调用了saveData。我已经模拟了传递给PersonalDetails的saveData函数,但是在mock上断言失败了(代码简称为简洁):

class Home extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            name: null
        };    
        this.saveData = this.saveData.bind(this);
    }

    render() {        
        return (
            <div>
                <PersonalDetails name={this.state.name} saveData={this.saveData}/>;
                <OtherThing saveData={this.saveData}/>
            </div>
        )
    }

    saveData(key, value){
        var d = {};
        d[key] = value;
        this.setState(d)
    }
}

PersonalDetails模块如下:

class PersonalDetails extends React.Component {

    constructor(props) {
        super(props);
        this.handleNameChange = this.handleNameChange.bind(this);
    }

    render() {            
        return (
            <div>
                <input onKeyPress={this.handleNameChange}
                       defaultValue={this.props.name}/>
            </div>
        )
    }

    handleNameChange(event) {
        if (event.nativeEvent.keyCode != 13) return;
        this.props.saveData('name',event.target.value)
    }
}

有问题的Jest测试用例:

it("saves data on change", function () {

    var saveData = jest.genMockFunction(); // mocking saveData
    const pdComponent = TestUtils.renderIntoDocument(
        <PersonalDetails saveData={saveData} name="My Name"/>
    );

    var input = TestUtils.findRenderedDOMComponentWithTag(
        pdComponent, 'input'
    );

    var node = ReactDOM.findDOMNode(input);
    node.value = "New Name"; // As per FB tests
    TestUtils.Simulate.change(node, {target: {value: "New Name"}});
    TestUtils.Simulate.keyDown(node, {key: "Enter", keyCode: 13, which: 13});
    expect(node.value).toBe("New Name"); // Passes
    // Fails
    expect(pdComponent.props.saveData).toBeCalledWith("New Name");
    // Also Fails
    expect(saveData).toBeCalledWith("New Name");

});

我在这里缺少什么想法?

2 个答案:

答案 0 :(得分:0)

你可以创建一个间谍。间谍是间谍,即保持跟踪。使用间谍,你可以检查功能是否被调用。

示例代码(从网上复制)

var CompSpec = {
  displayName: "Comp",

  plop: function() {
    console.log("plop");
  },

  render: function() {
    this.plop();
    return React.DOM.div("foo");
  }
};

var stub = sinon.stub(CompSpec, "plop");
var Comp = React.createClass(CompSpec);
React.addons.TestUtils.renderIntoDocument(Comp());

// plop() is properly stubbed, so you can
sinon.assert.called(stub); // pass

答案 1 :(得分:0)

问题的原因很简单但很难发现:

it('just an input test', () => {
    const keyPressAction = jest.fn(() => {
        console.log('key press');
    });

    const input = TestUtils.renderIntoDocument(<input type="text" onKeyPress={keyPressAction.bind(this)}/>);

    const inputNode: Element = ReactDOM.findDOMNode(input);

    inputNode.setAttribute('value', 'test');
    TestUtils.Simulate.keyPress(inputNode, {key: "Enter", keyCode: 13, which: 13});

    expect(input.getAttribute('value')).toEqual('test');
    expect(keyPressAction).toBeCalled();
});

将此与您问题中的解决方案进行比较。

对于输入元素,您使用onKeyPress事件,但在测试中您模拟了keyDown无效的测试,只需将其替换为keyPress,即可调用处理程序。

度过美好的一天!