React test; how to mock componentDidMount or overwrite it? React test; how to mock componentDidMount or overwrite it? reactjs reactjs

React test; how to mock componentDidMount or overwrite it?


I prefer the following approach, but requires using ES6 classes.

// component.jsxclass Component extends React.Component {    componentDidMount() { return this.setState({name: 'blabla'}); }    render() { return (<h1>{this.state.name}</h1>); }}//component-spec.jsxdescribe('Component', () => {    it('does stuff', () => {        let ComponentTest = class extends Component {            componentDidMount() {                 // your override here            }        };        let component = TestUtils.renderIntoDocument(<ComponentTest />);        //expect(component...).toEqual(...)    });});

The point is to create an on demand ChildClass inheriting the OriginalClass,do whatever overrides and then TestUtils.renderIntoDocument(<ChildClass />)


The idea here, if I understand correctly, is that you're trying to stub out a function before a component is rendered in your test. In your case, componentWillMount is only called once in a component's lifecycle, immediately before the component is rendered. So you can't just render the component and then stub out the function, it must be done before the render occurs.

Let's take these components for example:

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;

Here, we would want to stub out the test function before our Child component is rendered, otherwise, it will blow up.

I have been able to do this using jasmine-react. These helper functions provide some useful functionality when running tests, almost to the point where TestUtils can be ditched completely.

jasmineReact.render(component, [container]) will render an instance of component into the DOM node specified in [container]. This is like TestUtils.renderIntoDocument(), except it renders the component into an attached DOM node instead of a detached DOM node. It will also perform the necessary cleaning operations when the test is finished.

jasmineReact.spyOnClass(componentClass, functionName) will stub out a particular function belonging to a component class. This behavior is maintained until the end of the test, which means that you can call this function before a component is rendered. This, if I understand correctly, is what you're looking for.

So, using these two helper functions, I can write a test for the code shown above that looks something like this:

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    });});

Let me know if you have any questions.


I've found two ways to go about this (i'm sure there are more).

1) I've used sinon-chai and required in the base element class and then use rewireify to put a set a spy on the componentWillMount method. This works but not sure what test suites you're using.

2) Probably the easier way. Is to just use the TestUtils to get an instance of the component and then just manually run the componentWillMount method.

That second way would probably look something like (forgive the pesudo code):

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');});