使用 enzyme、mocha、sinon 和 reactjs 进行单元测试。如何查看间谍被调用的内容?

Unit test with enzyme, mocha, sinon and reactjs. How to see what the spy is called with?

我试图弄清楚此测试失败的原因,但无法确定原因,因为我看不到正在调用什么 sinon 间谍对象。

是否有更好的方法来测试 sinon.calledWith 以便显示结果和预期结果?

在下面的测试中,以下检查通过 expect(onLoginClick.called).to.equal(true); 但未通过 expect(onLoginClick.calledWith(expected)).to.equal(true);

  1. 知道为什么吗?
  2. 我如何通过查看调用 onLoginClick 的实际值与预期值来检查自己?

我正在 运行 通过 "npm run test" 进行测试,可以从 https://github.com/Rob-Leggett/react_redux_webpack

克隆项目和 运行

感谢您的回答和花时间来协助解决这个问题。

测试

import React from 'react';
import { mount, shallow } from 'enzyme';
import { expect } from 'chai';
import sinon from 'sinon';

import Login from '../app/components/login/Login';

describe('<Login/>', function () {

  it('should click login button with credentials', () => {
      // given
      const expected = { username: 'test', password: 'user' };

      const errors = [];
      const onLoginClick = sinon.spy();

      const wrapper = mount(<Login errors={errors} onLoginClick={onLoginClick} />);

      // when
      wrapper.ref('username').simulate('change', {target: {value: 'test'}});
      wrapper.ref('password').simulate('change', {target: {value: 'user'}});

      wrapper.find('button').simulate('click');

      // then
      //expect(onLoginClick.calledWith(expected)).to.equal(true);
      expect(onLoginClick.called).to.equal(true);
  });
});

组件

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

export default class Login extends Component {

  renderErrors() {
    const { errors } = this.props;

    return errors.map((error, i) => {
      return (
          <p key={i} style={{color:'red'}}>{error}</p>
      );
    });
  }

  render() {
    return (
        <div>
          <input type='text' ref='username' className="form-control" style={{ marginRight: '5px' }} placeholder='Username'/>
          <input type='password' ref='password' className="form-control" style={{ marginRight: '5px' }} placeholder='Password'/>
          <button onClick={() => this.handleLogin()} className="btn btn-primary">
            Login
          </button>

          {this.renderErrors()}
        </div>
    )
  }

  handleLogin() {
    const { onLoginClick } = this.props;

    const credentials = {
      username: this.refs.username.value.trim(),
      password: this.refs.password.value.trim()
    };

    onLoginClick(credentials)
  }
}

Login.propTypes = {
  onLoginClick: PropTypes.func.isRequired,
  errors: PropTypes.arrayOf(PropTypes.string)
};

package.json

{
  "name": "react_redux_webpack_client",
  "version": "1.0.0",
  "description": "A ReactJS Client",
  "scripts": {
    "test": "mocha test/helpers/browser.js test/**/*.spec.js",
    "dev": "webpack-dev-server --content-base public/ --hot --inline",
    "build": "webpack -p --display-error-details"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/Rob-Leggett/react_redux_webpack.git"
  },
  "author": "Robert Leggett",
  "license": "MIT",
  "homepage": "https://github.com/Rob-Leggett/react_redux_webpack",
  "bugs": {
    "url": "https://github.com/Rob-Leggett/react_redux_webpack/issues"
  },
  "devDependencies": {
    "chai": "^3.5.0",
    "css-loader": "^0.26.1",
    "enzyme": "^2.7.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "html-webpack-plugin": "^2.26.0",
    "jsdom": "^9.9.1",
    "mocha": "^3.2.0",
    "node-sass": "^4.3.0",
    "react-addons-test-utils": "^15.4.2",
    "sass-loader": "^4.1.1",
    "sinon": "^1.17.7",
    "style-loader": "^0.13.1",
    "webpack": "^1.14.0",
    "webpack-dev-server": "^1.16.2"
  },
  "dependencies": {
    "babel-core": "^6.21.0",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-react": "^6.16.0",
    "babel-register": "^6.22.0",
    "body-parser": "^1.15.2",
    "classnames": "^2.2.5",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-redux": "^5.0.2",
    "redux": "^3.6.0",
    "redux-thunk": "^2.2.0",
    "whatwg-fetch": "^2.0.1"
  }
}

要在你的测试中找到比 true/false 更多的信息,你可以像这样从 Sinon 间谍中获取参数:

const spyCall = onLoginClick.getCall(0);
expect(spyCall.args[0]).to.equal(expected)

现在,失败的测试应该会向您展示您真正获得的参数。 参见 http://sinonjs.org/docs/