使用Sinon在Javascript中测试私有成员

Rob*_*bie 16 javascript testing mocha.js sinon

我开始编写一些javascript测试并试图找出检查模块构造函数的私有成员的最佳方法.例如,在下面的示例中,我使用揭示模块模式将公共API暴露给我的模块.我想测试privateVar$.getJSONajax请求的回调期间正确设置.

第二个测试it('should update privateVar', ...),不起作用,因为myModule.privateVar(故意)不在模块的公共API中.

所以,我的问题是,测试这种行为的最佳方法什么,而不必将privateVar作为公共API的一部分?是否有更好的方法可以将此代码用于测试,或者使用像SinonJs这样的方法来监视私有成员?

define('myModule',
    ['jquery'],
    function ($) {
        var
            myVar = "something",
            privateVar = "something else",

            doSomething = function() {
                return $.getJSON('http://myapi.com/do-something', { requestData : "some data" }, function(response){
                    myVar = response.data.value1;
                    privateVar = response.data.value2;
                });
            };

        return {
            doSomething : doSomething,
            myVar : myVar
        };
    }
);

define('test/test.myModule',
    ['myModule', 'chai', 'sinon', 'mocha'],
    function (myModule, chai, sinon) {

        describe("myModule", function() {
            var expect = chai.expect;

            describe('doSomething', function() {

                var value1 = 'value1 value',
                    value2 = 'value2 value';

                beforeEach(function() {
                    sinon.stub($, 'ajax').yieldsTo('success', {
                        data : { value1 : value1, value2 : value2 }
                    });
                });

                afterEach(function() {
                    $.ajax.restore();
                });

                it('should update myVar', function(done) {
                    myModule.doSomething();
                    expect(myModule.myVar).to.equal(value1);
                    done();
                });

                it('should update privateVar', function(done) {
                    myModule.doSomething();
                    expect(myModule.privateVar).to.equal(value2);
                    done();
                });
            });


        });

    }
);
Run Code Online (Sandbox Code Playgroud)

kry*_*our 6

你在这里谈论的不幸的是需要进行集成测试,你希望测试一个变量是由于外部操作而设置的,你应该相信外部方法只适用于你的测试,因为你在测试中将其存在已经完成了sinon,这照顾外部呼叫.

您需要做的是控制测试的条件(假设未经过身份验证和验证),然后测试该实例中函数的结果.作为一项规则,我通常不会测试私人成员,但我会测试由已知的好的和坏的值导致的所需行为.

我不久前也读过这篇文章,讨论私人变量.


roc*_*hal 3

通过这种方式访问​​私有变量的唯一方法是添加一个公共 getter,稍后您可以在测试中调用该 getter 来验证状态:

在你的班级:

getPrivateVar : function(){ 返回 privateVar; }

然后添加返回语句:

返回 { getPrivateVar : getPrivateVar, };

  • 谢谢@rochal,是的,这会起作用,但是说我的 privateVar 是一些秘密,比如我不想暴露的身份验证令牌。添加这样的 getter 实际上与将 var 放入公共 api 中是一样的。老实说,我不确定这是否是一个合理的担忧。 (2认同)
  • 不,您不应修改测试代码。私有方法之所以私有是有原因的。 (2认同)