【问题标题】:Testing private members in Javascript using Sinon使用 Sinon 在 Javascript 中测试私有成员
【发布时间】:2013-02-25 11:56:02
【问题描述】:

我开始编写一些 javascript 测试并试图找出检查模块构造函数的私有成员的最佳方法。例如,在下面的示例中,我使用显示模块模式将公共 api 公开给我的模块。我想在$.getJSON ajax 请求的回调过程中测试privateVar 是否正确设置。

第二个测试 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();
                });
            });


        });

    }
);

【问题讨论】:

  • 这应该对测试私人成员的主题有所了解:stackoverflow.com/questions/105007/…
  • @AdityaManohar 感谢您的链接。就我而言,我实际上是在测试一个公共方法,但我想确保它正确设置了一个非公共属性。

标签: javascript testing mocha.js sinon


【解决方案1】:

不幸的是,您在这里谈论的内容需要集成测试,您希望测试一个变量是否是由外部操作设置的,您应该相信外部方法只适用于您的测试,方法是在您的像你对 sinon 所做的测试,这会处理外部调用。

您需要做的是控制测试的条件(比如说未经身份验证和身份验证),然后测试该实例中函数的结果。作为一项规则,我通常根本不测试私有成员,但我会测试由已知的好值和坏值产生的期望行为..

我不久前还阅读了this,其中讨论了私有变量。

【讨论】:

  • 这不是一个真正的集成测试,因为正如你所指出的,我已经将 ajax 调用存根以隔离 SUT,因此没有测试“外部操作”的结果,而是结果逻辑的行为是。
【解决方案2】:

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

在你的课堂上:

getPrivateVar : function(){ return privateVar; }

然后添加到return语句:

return { getPrivateVar : getPrivateVar, };

【讨论】:

  • 谢谢@rochal,是的,这会起作用,但是说我的 privateVar 是秘密的,比如我不想暴露的身份验证令牌。添加这样的 getter 实际上与将 var 放入公共 api 中的效果相同。老实说,我不确定这是否是一个有效的问题。
  • 不,您不应该修改测试代码。私有方法是私有的是有原因的。
【解决方案3】:

实际上为什么要测试私有变量?这是不可能/困难的。 该变量的目的是什么?如果要作为参数传递给函数,当然可以通过监视函数是否使用分配给私有变量的特定值来调用函数来测试函数。

【讨论】:

    【解决方案4】:

    您可以使用重新布线

    let revertBack = renderCtrl.__set__(privateMember,substituteMember);
    

    要恢复,只需调用 revertBack(); 更多详情见https://www.npmjs.com/package/rewire

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-31
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-25
      相关资源
      最近更新 更多