Подтвердить что ты не робот

Реактивный тест; как имитировать компонентDidMount или перезаписать его?

Я пытаюсь проверить компонент реакции.

var Component = React.createClass({

  componentDidMount: function () {

    return this.setState({
      name: 'blabla'
    });
  },

  render: function () {

    return (
      <h1>{this.state.name}</h1>
    );
  }
});

Есть ли способ во время тестирования издеваться над тем, что componentDidMount возвращает или делает? Это оставило бы меня проверить его на собственном опыте и просто проверить поведение компонента.

Спасибо!

4b9b3361

Ответ 1

Идея здесь, если я правильно понимаю, заключается в том, что вы пытаетесь отключить функцию до того, как компонент будет показан в вашем тесте. В вашем случае componentWillMount вызывается только один раз в жизненном цикле компонента, непосредственно перед визуализацией компонента. Таким образом, вы не можете просто визуализировать компонент и , а затем затушить функцию, это должно быть сделано до рендеринга.

Давайте возьмем эти компоненты, например:

parent.js

var Child = require('./child.js');
var Parent = React.createClass({
    render : function () {
        return (
            <div className="parent">
                <Child/>
            </div>
        );
    }
});
module.exports = Parent;

child.js

var Child = React.createClass({
    test : function () {
        return true;
    },
    render : function () {
        if (this.test) {
            throw('boom');
        }
        return (
            <div className="child">
                Child
            </div>
        );
    }
});
module.exports = Child;

Здесь мы хотели бы отключить функцию test до отображения нашего дочернего компонента, иначе он взорвется.

Я смог сделать это, используя jasmine-react. Эти вспомогательные функции предоставляют некоторые полезные функции при запуске тестов, почти до такой степени, что TestUtils можно полностью отбросить.

jasmineReact.render(component, [container]) отобразит экземпляр component в DOM node, указанный в [container]. Это похоже на TestUtils.renderIntoDocument(), за исключением того, что компонент превращается в прикрепленный DOM node вместо отсоединенной DOM node. Он также выполнит необходимые операции очистки после завершения теста.

jasmineReact.spyOnClass(componentClass, functionName) закроет определенную функцию, принадлежащую классу компонентов. Это поведение сохраняется до конца теста, что означает, что вы можете вызвать эту функцию до, если компонент визуализирован. Это, если я правильно понимаю, это то, что вы ищете.

Итак, используя эти две вспомогательные функции, я могу написать тест для приведенного выше кода, который выглядит примерно так:

var React = require('react/addons'),
    Parent = require('./parent.js'),
    Child = require('./child.js'),
    jasmineReact = require('jasmine-react-helpers');

describe('Parent', function () {
    it('does not blow up when rendering', function () {
        jasmineReact.spyOnClass(Child, 'test').and.returnValue(false);
        var parentInstance = jasmineReact.render(<Parent/>, document.body); //does not blow up
        expect(parentInstance).toBeTruthy(); //passes
    });
});

Сообщите мне, если у вас есть какие-либо вопросы.

Ответ 2

Я предпочитаю следующий подход, но требует использования классов ES6.

// component.jsx
class Component extends React.Component {
    componentDidMount() { return this.setState({name: 'blabla'}); }
    render() { return (<h1>{this.state.name}</h1>); }
}

//component-spec.jsx
describe('Component', () => {
    it('does stuff', () => {
        let ComponentTest = class extends Component {
            componentDidMount() { 
                // your override here
            }
        };
        let component = TestUtils.renderIntoDocument(<ComponentTest />);
        //expect(component...).toEqual(...)
    });
});

Дело в том, чтобы создать ChildClass по требованию, наследующий OriginalClass, делать все переопределения, а затем TestUtils.renderIntoDocument(<ChildClass />)

Ответ 3

Я нашел два способа сделать это (я уверен, что их больше).

1) Я использовал sinon-chai и потребовался в классе базового элемента, а затем использовал rewireify, чтобы установить шпион по методу componentWillMount. Это работает, но не уверен, какие тестовые комплекты вы используете.

2) Вероятно, это проще. Следует просто использовать TestUtils для получения экземпляра компонента, а затем просто вручную запустить метод componentWillMount.

Этот второй способ, вероятно, будет выглядеть примерно так (простить код pesudo):

it('should call state when it first mounts', function () {
  var Component = require('../my-component');
  var component = TestUtils.renderIntoDocument(<Component />);

  component.setState({name: null});
  component.componentWillMount();

  expect(component.state.name).to.equal('blabla');
});