如何使用反射组件构造函数来监视?单元测试?

时间:2016-11-29 01:22:10

标签: javascript unit-testing reactjs sinon expect.js

我正在使用酶,sinon并期望对我的反应成分进行单元测试。

import React from 'react';
import expect  from 'expect.js';
import { shallow } from 'enzyme';

import ExampleComponent from './../../../src/js/components/example-component';

describe('Test <ExampleComponent />', function() {

beforeEach(function() {
    this._sandbox = sinon.sandbox.create();
    this.constructorSpy = this._sandbox.spy(ExampleComponent.prototype, 'constructor');
});

afterEach(function() {
    this._sandbox.restore();
    this.constructorSpy = null;
});

it('Should set the state with the correct data [constructor]', function() {
    const wrapper = shallow(<ExampleComponent />);
    console.log(' - callCount: ', this.constructorSpy.callCount);
    expect(this.constructorSpy.calledOnce).to.be(true);

    expect(Immutable.is(wrapper.state('shownData'), Immutable.Map())).to.be(true);
});

我的组件构造函数中有一些逻辑,它根据我作为props传递的内容设置状态。但是,这个测试一直告诉我构造函数调用次数为0并且没有调用它。

监视组件构造函数的正确方法是什么?我做错了什么?

我正在使用沙箱,因为我希望将来还有其他功能添加到沙箱中进行间谍活动。

1 个答案:

答案 0 :(得分:4)

当shallow shallow呈现测试时,应自动调用构造函数(以及任何其他生命周期方法)。试图在测试中覆盖它可能会非常复杂,并且对于您要检查的内容而言并不是必需的。

如果构造函数基于props设置状态,为什么检查测试中的结果状态不够? (参见下面例子中的“非常重要”断言)

另一种选择:假设您正在设置状态中的项目然后在组件渲染中使用 - 在这种情况下,您可以只检查渲染元素中的这些项目。

最后,我还在构造函数中包含了一个函数调用,然后我在测试中使用sinon(使用sinon)断言它被调用,以防它有用。

示例React组件:

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

export default class Post extends Component {
  static propTypes = {
    markRead: PropTypes.func.isRequired,
    postName: PropTypes.string.isRequired
  }

  constructor (props) {
    super(props)
    const { markRead, postName } = props

    markRead()
    this.state = {
      postName: 'Very Important: ' + postName
    }
  }

  render () {
    const { postName } = this.state

    return (
      <div className='post-info'>
        This is my post: {postName}!
      </div>
    )
  }
}

酶测试示例,全部通过:

import React from 'react'
import assert from 'assert'
import { shallow } from 'enzyme'
import { spy } from 'sinon'

import Post from 'client/apps/spaces/components/post'

describe('<Post />', () => {
  const render = (props) => {
    const withDefaults = {
      markRead: () => {},
      postName: 'MyPostName',
      ...props
    }
    return shallow(<Post {...withDefaults} />)
  }

  it('renders and sets the post name', () => {
    const markReadSpy = spy()
    const props = {
      markRead: markReadSpy
    }
    const wrapper = render(props)
    const postInfo = wrapper.find('.post-info')
    const postText = postInfo.text()

    assert.equal(wrapper.state('postName'), 'Very Important: MyPostName')
    assert(markReadSpy.calledOnce)
    assert.equal(postInfo.length, 1)
    assert(postText.includes('MyPostName'))
  })
})

注意:另外,看起来好像你没有在fyi上面的示例中导入sinon。