Sinon.js - 在组件实例化之前存根React组件的函数?

8
假设我有一个长这样的组件:
var React = require('react/addons');

var ExampleComponent = React.createClass({
    test : function () {
        return true;
    },
    render : function () {
        var test = this.test();
        return (
            <div className="test-component">
                Test component - {test}
            </div>
        );
    }
});

module.exports = ExampleComponent;

在我的测试中,我可以使用TestUtils来呈现此组件,然后像这样存根方法:
var renderedComponent = TestUtils.renderIntoDocument(<ExampleComponent/>);
sinon.stub(renderedComponent, 'test').returns(false);
expect(renderedComponent.test).toBe(false); //passes

但是有没有一种方法可以让Sinon在每次创建组件实例时自动桩数据函数?例如:
sinon.stubAll(ExampleComponent, 'test').returns(false); //something like this
var renderedComponent = TestUtils.renderIntoDocument(<ExampleComponent/>);
expect(renderedComponent.test).toBe(false); //I'd like this to pass

如果不可能做到这一点,是否有一种潜在的解决方案接近我所寻找的功能?
2个回答

16

你需要覆盖ExampleComponent.prototype而不是ExampleComponent本身。 ExampleComponent是一个构造函数,像test()这样的本地方法保存在它的prototype中。

sinon.stub(ExampleComponent.prototype, 'test').returns(false);
var renderedComponent = TestUtils.renderIntoDocument(<ExampleComponent/>);
expect(renderedComponent.test).toBe(false); //passes

感谢您的回答。虽然它似乎对某些情况有效,但并不完全符合我的要求。我可能应该更具体地说明一下。我有一个父组件和一个子组件,子组件在父组件的render方法中呈现。父组件使用require()获取构造函数,在我的测试中似乎没有办法覆盖子组件的原型。这有意义吗?如果您愿意,我可以用示例更新我的问题。 - Michael Parker
1
如果您能提供一个例子来扩展这个问题,那就太好了。 - Victor
我找到了一个可行的解决方案,但我仍然会授予你奖励。 - Michael Parker

3

我找到了解决问题的方法。

为了澄清,我的问题是我想要存根渲染在父组件下的子组件所属的函数。就像这样:

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;

如果我在测试中使用TestUtils来渲染Parent组件,它会抛出错误,而我想要避免这种情况。我的问题是,在实例化Child组件之前,我需要存根化它的test函数。然后,当我渲染Parent组件时,Child组件就不会崩溃。
提供的答案并没有完全解决问题,因为Parent组件使用require()来获取Child组件的构造函数。我不知道为什么,但因为这个原因,我不能在测试中存根化Child组件的原型并期望测试通过,代码如下:
var React = require('react/addons'),
    TestUtils = React.addons.TestUtils,
    Parent = require('./parent.js'),
    Child = require('./child.js'),
    sinon = require('sinon');

describe('Parent', function () {
    it('does not blow up when rendering', function () {
        sinon.stub(Child.prototype, 'test').returns(false);
        var parentInstance = TestUtils.renderIntoDocument(<Parent/>); //blows up
        expect(parentInstance).toBeTruthy();
    });
});

我找到了一个适合我的需求的解决方案。我将我的测试框架从Mocha改为Jasmine,并开始使用jasmine-react,它提供了一些好处,包括在类实例化之前存根函数的能力。下面是一个可行的解决方案的示例:

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

我希望这能帮助到其他遇到类似问题的人。如果有任何问题,我很乐意提供帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接