【问题标题】:How to mock a function inside another function (which I am testing) using sinon?如何使用 sinon 在另一个函数(我正在测试)中模拟一个函数?
【发布时间】:2017-06-27 09:18:00
【问题描述】:

假设我有一个函数

Func a() {
    //Do Something
    let c = b();
    return c;
}

我想测试函数 a 和模拟 b() 并在模拟中分配 c。 Sinon.Stub(Test,"b").returns("DummyValue"); c 应该被分配 DummyValue。

我该怎么做?

describe("a", () => {
    let a = a();
    //mock b();
    action = execute(a);
    expect(action).should.return.("DummyValue");
})

【问题讨论】:

    标签: javascript function mocking mocha.js sinon


    【解决方案1】:

    当我们在同一个文件中有 2 个函数并且想要存根其中一个并测试另一个时。 例如,: 测试:tests.js

    let ComputeSumStub = sinon.stub(OfflineLoader, "ComputeSum");
    const ans = function ()
    {
        return 10;
    };
    ComputeSumStub.returns(ans);
    const actualValue: number = OfflineLoader.sum();
    expect(actualValue).to.be.equal(10);
    

    开发:foo.js

    function sum(): number
    {
        return ComputeSum(8, 9);
    }
    
    function ComputeSum(a: number, b: number): number
    {
        return a + b;
    }
    

    我们不能这样做,因为在编译后,函数以不同的签名导出,具有全名,并且在存根时我们存根全局函数,但在从另一个函数中调用它时,我们调用本地函数,因此它没有不工作。 有一种解决方法可以做到这一点。

    foo.js
    const factory = {
      a,
      b,
    }
    function a() {
      return 2;
    }
    
    function b() {
      return factory.a();
    }
    
    module.exports = factory;
    

    test.js

    const ser = require('./foo');
    const sinon = require('sinon');
    
    const aStub = sinon.stub(ser, 'a').returns('mocked return');
    console.log(ser.b());
    console.log(aStub.callCount);
    

    参考:Stubbing method in same file using Sinon

    【讨论】:

    • 什么是OfflineLoader,它来自哪里?
    【解决方案2】:

    你只能存根函数

    • 如果你把它作为参数传递,然后用像sinon这样的测试双打库来伪造它
    • 或者如果它是依赖项(通过importrequire 加载)。在这种情况下,您可以使用proxyquire 将您的假b 函数传递给被测模块。函数本身可以被sinon 或其他测试替身库伪造。

    【讨论】:

      【解决方案3】:

      在这种情况下,sinon 存根比模拟更合适 何时使用模拟与存根?

      经验法则是:如果你不想为某些人添加断言 具体调用,不要嘲笑它。请改用存根。

      我们在测试中的断言不是针对函数的特定调用,即第一次或第三次调用,而是针对所有调用。

      我们可以这样判断,因为我们已经将存根编程为始终返回相同的结果,而不管它被调用的方式(参数或调用次数)。

      将 sinon 存根函数作为参数传递给函数 a。

      Function a(b) {
          const c = b();
      
          return c;
      }
      

      test.js

      require("sinon")
      
      describe("a", () => {
          const stub = sinon.stub();
          stub.returns("DummyValue");
          expect(a(stub)).to.eql.("DummyValue");
      })
      

      请注意,我们可以将 const 用于这些变量声明,因为它们永远不会被重新分配。

      【讨论】:

      • 我不想将函数/存根作为参数传递。我想在不传递函数 b 的情况下做到这一点。有可能吗?
      • 可能但不推荐通过 rewire 库之类的东西。 Monkey patching 是在运行时修改模块或包以改变执行过程的艺术。因此,您将是猴子补丁。我相信我的方法比安装外部模块来更改运行时的执行更简单。
      猜你喜欢
      • 2017-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 2018-08-13
      • 2017-03-23
      • 2020-05-13
      相关资源
      最近更新 更多