【问题标题】:Sinon stub function used with destructuring与解构一起使用的 Sinon 存根函数
【发布时间】:2019-03-06 09:06:43
【问题描述】:

我希望对当前正在测试的文件中使用的函数进行存根。像这样的解构需要这个函数:

 const { theFunctionIWant } = require('path/to/module')

在测试时,永远不会调用存根,而是继续调用真正的函数。 但是当我“通常”需要它时(即:没有解构)

const myModule = require('path/to/module')

然后正确使用存根,一切正常

我感觉这是因为解构的工作方式以及sinon 存根对象属性而不是直接存根函数的事实。无论如何,如果您能给我一些见解,我将不胜感激!

【问题讨论】:

    标签: node.js unit-testing sinon


    【解决方案1】:

    当使用依赖模块的解构时,存根模块方法不起作用的原因非常简单,并且与绑定实际函数引用的时间有关。它与 CommonJS 模块、Sinon 或 Node 本身没有任何关系,所以我将从简单的 javascript 示例开始。

    const stub = (o, method) => (o[method] = () => "I am a stub");
    
    const obj = {
      methodFoo() {
        return "I am foo";
      }
    };
    
    // same as doing `const methodFoo = obj.methodFoo;`
    const { methodFoo } = obj; // "import" using destructuring
    
    console.log("obj.methodFoo(): ", obj.methodFoo());
    console.log("methodFoo()", methodFoo());
    
    console.log("Stubbing out method!");
    stub(obj, "methodFoo");
    
    console.log("obj.methodFoo: ", obj.methodFoo());
    console.log("methodFoo()", methodFoo());

    如果你运行上面的例子,你会看到,即使 你已经存根了obj“模块”的methodFoo属性, 直接绑定的引用仍然返回旧值!

    这是因为,在存根时,您实际上是在分配 对象属性的新值(函数)(此处为:obj)。对这个新值的新引用(使用obj.methodFoo)将打印新值, 但是如果你已经存储了对旧函数的引用你会 调用旧函数时仍然得到旧的返回值。

    这同样适用于您的原始问题。如果您在模块 A 中有依赖项 在模块 B 中的函数 foo 上并 store 该引用,然后 是否分配一个新值(例如存根)并不重要 导出的值,因为您已经存储了对旧值的引用。

    本质上:

    这将受到存根的影响

    const A = require('./A');
    
    function doFoo(){
        A.foo(); // will always evalute  A['foo']()
    }
    

    这不会受到存根的影响

    const myFoo = require('./A').foo;
    
    function doFoo(){
        myFoo(); // will just evalute to the original value of A.foo()
    }
    

    【讨论】:

    • 感谢您的回答和清晰的解释!
    • 不用担心;很高兴能提供帮助。
    • @oligofren 很好的解释。那么,在使用destructor时,没有办法阻止原函数的执行?
    • 根据我对您问题的理解,不,不单独使用诗乃。您将需要一些挂钩到模块的实际加载并替换它的东西,以及如何配置它取决于您的环境(纯 Node、Browserify、Webpack ......)。示例:rewireproxyquire。有关示例,请参见 sinonjs.org/how-to。
    【解决方案2】:

    由于您的模块返回一个对象并且theMethodIwant 是该对象的属性,您可以像这样定义您的存根:

    const myModule = require('path/to/module')
    myModule.theMethodIwant = sinon.stub()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-17
      • 2019-07-28
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 2015-06-04
      相关资源
      最近更新 更多