使用Jasmine在react组件上测试onClick事件

时间:2016-03-25 07:15:03

标签: unit-testing reactjs jasmine

我有一个React组件,该组件具有按钮,onClick事件被绑定到从父组件作为属性传递的函数,例如, <Counter counter=0 incrementCounter={incrementFunction} decrementCounter={decrementFunction} />

我是单位测试React组件的新手,所以我试图在点击增量/减量按钮时检查函数是否被调用。为此,我使用的是Jasmine的spyOn方法,但它似乎永远不会捕获被调用的函数。

如果我在我正在使用的函数中输出一个console.log(例如let incrementCounter = () => { console.log("increment!"); };),那么当我执行TestUtils.Simulate.click(incrementButton);时我可以告诉函数被调用,但测试仍然不会通过。我错过了什么?

Counter.js

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

class Counter extends Component {

  constructor(props) {
    super(props);
  }

  render() {
    const { incrementCounter, decrementCounter, counter } = this.props;
    return (

        <div>
          <h1>Counter</h1>
          <p>
            <b>Counter: {counter} times</b>
            {" "}
            <button onClick={incrementCounter}>+</button>
            {" "}
            <button onClick={decrementCounter}>-</button>
          </p>
        </div>

    );
  }
}

Counter.propTypes = {
  incrementCounter: PropTypes.func.isRequired,
  decrementCounter: PropTypes.func.isRequired,
  counter: PropTypes.number.isRequired
};

export default Counter;

Counter.test.js

import React from "react";
import TestUtils from "react/lib/ReactTestUtils";
import Counter from "./Counter"

describe("Counter", function () {

  let renderedComponent = {};
  let heading = {};
  let decrementButton = {};
  let incrementButton = {};
  let incrementCounter = () => {};
  let decrementCounter = () => {};
  let counter = 0;

  beforeEach(function(){

    renderedComponent = TestUtils.renderIntoDocument(
        <Counter incrementCounter={incrementCounter} decrementCounter={decrementCounter} counter={counter} />
    );

    heading = TestUtils.findRenderedDOMComponentWithTag(renderedComponent, "h1");

    let buttons = TestUtils.scryRenderedDOMComponentsWithTag(renderedComponent, "button");

    decrementButton = buttons[1];
    incrementButton = buttons[0];

    this.incrementCounter = incrementCounter;

  });

  it("renders without problems", function () {

    expect(TestUtils.isDOMComponent(heading)).toBe(true);
    expect(heading.innerText).toMatch(/Counter/g);

    expect(TestUtils.isDOMComponent(decrementButton)).toBe(true);
    expect(decrementButton.innerText).toMatch(/-/g);

    expect(TestUtils.isDOMComponent(incrementButton)).toBe(true);
    expect(incrementButton.innerText).toMatch(/\+/g);

  });

  it("fires the increment function", function() {

    spyOn(this, "incrementCounter");
    TestUtils.Simulate.click(incrementButton);
    expect(this.incrementCounter).toHaveBeenCalled(); // Error: fuction doesn't get called

  });

});

1 个答案:

答案 0 :(得分:1)

我不太确定Jasmine如何实际使用spyOn包装函数,但请尝试在this.incrementCounter = incrementCounter的顶部设置beforeEach并直接在组件中使用它:

beforeEach(function(){
  let that = this;
  this.incrementCounter = incrementCounter;
  renderedComponent = TestUtils.renderIntoDocument(
    <Counter incrementCounter={that.incrementCounter} decrementCounter={decrementCounter} counter={counter} />
);

如果由于that / this出现故障仍然无法解决问题,请从一开始就将incrementCounter声明为间谍:

let incrementCounter = jasmine.createSpy('incrementCounter')

并在<Counter />和其他测试中使用它。