如何在Sinon中存根一系列方法?

时间:2016-06-21 15:07:31

标签: javascript unit-testing sinon

我知道如何使用stub来替换一个函数。

len(set(sc.parallelize(range(4), 4).map(lambda _: random.getstate()).collect()))
# 1

但是现在我在我的函数中有一行我想测试我需要看起来像这样的存根

sandbox.stub(Cars, "findOne",
            () => {return car1 });

所以这里有一系列功能,我不确定我需要做什么。我如何存根"找到"返回我可以用来存根的东西" fetch"?

7 个答案:

答案 0 :(得分:11)

恕我直言,我们可以只使用returns来做到这一点。我们不需要使用callsFake或将其模拟为函数。

// Cars.find().fetch()

sinon.stub(Cars, 'find').returns({
  fetch: sinon.stub().returns(anything);
});

如果在 fetch()之后还有另一种方法,我们可以使用returnsThis()

// Cars.find().fetch().where()

sinon.stub(Cars, 'find').returns({
  fetch: sinon.stub().returnsThis(),
  where: sinon.stub().returns(anything);
});

参考: https://sinonjs.org/releases/v6.3.3/

希望有帮助

答案 1 :(得分:7)

试试这个:

sandbox.stub(Cars, "find", () => {
    return {
        fetch: sinon.stub().returns(anything);
    };
});

答案 2 :(得分:2)

将函数附加到存根的形式如下所示:

sandbox.stub(Cars, "find", () => {
    return {
        fetch: sinon.stub().returns(anything);
    };
});

已弃用。

现在version 6.3为止

sandbox.stub(Cars, "find").callsFake(() => {
    return {
        fetch: sinon.stub().returns(anything);
    };
});

答案 3 :(得分:1)

我遇到了这个问题,尽管我喜欢单个测试的解决方案,但我希望它具有更多的动态性,以允许跨测试重复使用。我也更喜欢沙盒方法,因为它使大型套件的恢复变得容易得多。最终结果:

export function setupChainedMethodStub(sandbox: sinon.SinonSandbox, obj: any, methodName: string, methodChain: string[], value: any) {
    return sandbox.stub(obj, methodName).returns(generateReturns(sandbox, methodChain, value));
}

function generateReturns(sandbox: sinon.SinonSandbox, methodChain: string[], value: any): any {
    if (methodChain.length === 1) {
        return {
            [methodChain[0]]: sandbox.stub().returns(value),
        };
    } else {
        return {
            [methodChain[0]]: sandbox.stub().returns(generateReturns(sandbox, methodChain.slice(1), value)),
        };
    }
}

无论何时要设置存根,我都要传入创建的沙箱和其他参数:

setupChainedMethodStub(sandbox, MyMongooseModel, 'findOne', ['sort', 'exec'], { foo: 'bar' })

然后我在最高范围的sandbox.restore()中只有一个afterEach()

答案 4 :(得分:0)

这是另一种允许在jQuery方法链上进行间谍活动的方法 - 这花了我很长时间才弄明白。

在示例中,我正在尝试测试电子邮件字段已清除

    //set up stub and spy
    const valSpy = sandbox.spy();
    const jQueryStub = sandbox
      .stub($.prototype, "find")       // this prototype is important
      .withArgs("input[name=email]")
      .returns({ val: valSpy });

    // call function under test
    learnerAlreadyAccepted(inviteDoc);

    // check expectations
    expect(jQueryStub).to.have.been.called;      // not really necessary
    expect(valSpy).to.have.been.calledWith("");

并且测试中的函数是(粗略地):

  learnerAlreadyAccepted = function(doc) {
    $("form").find("input[name=email]").val("");
  }

答案 5 :(得分:0)

我有一个简单的解决方案,希望能对其他人有用。

假设fetch也是Cars上的方法,并且fetchfind支持方法链接,Cars可能看起来像这样:

class Cars {
  fetch() {
    // do stuff
    return this;
  }

  find() {
    // do stuff
    return this;
  }
}

[ANSWER]我们应该能够使用存根支持方法链接,如下所示:

  sandbox.stub(Cars, 'fetch').callsFake(function () { return this; }); // optional
  sandbox.stub(Cars, 'findOne').callsFake(function () { return this; });

答案 6 :(得分:0)

v2.0进行了一些更改。

More details here

其中之一是:

stub(obj, 'meth', fn) has been removed, see documentation

您可以降级,但我不建议这样做,相反,您可以执行以下操作:

let stub = sinon.stub(obj, "meth").callsFake(() => {
  return {
    meth2: sinon.stub().callsFake(() => {
      return {
        meth3: sinon.stub().returns(yourFixture),
      };
    }),
  };
});