云功能单元测试模拟新文档ID

人气:219 发布:2022-10-16 标签: typescript google-cloud-firestore google-cloud-functions sinon

问题描述

对于FiRestore云函数类型脚本单元测试,我想模拟doc().id,但不是doc('path')。我应该怎么做?

admin.firestore().collection('posts').doc().id // I only want to mock this one

admin.firestore().collection('posts').doc('1')

我尝试在SINON中执行以下操作。但它在sinon/proxy-invoke.js:50:47

处陷入无限循环
const collection = admin.firestore().collection('posts');
sinon.stub(collection. 'doc').callsFake(path => 
   path === undefined ? mock : collection.doc(path)
);
sinon.stub(admin.firestore(), 'collection')
  .callThrough()
  .withArgs('posts')
  .returns(collection)

我还尝试了以下方法。但是doc(documentPath: string)方法似乎也被清除了:

sinon.stub(collection, 'doc')
  //@ts-ignore
  .withArgs()
  .returns(mock)

如果有解决办法,我愿意使用其他模拟库。

推荐答案

您得到一个无限循环,因为您递归地调用存根方法:

sinon.stub(collection, 'doc').callsFake(path => 
   path === undefined ? mock : collection.doc(path) // <- this calls the stub again
);
首先,您需要从要存根的对象中提取原始的doc方法。您还必须使用传统的function语法,以便将this正确地传递给伪回调(您还应该将其传递给您调用的任何其他函数)。虽然此doc函数只接受单个路径参数,但您应该养成使用REST参数的习惯,以确保您处理的是所有参数。

// store the raw function (make sure this only happens
// once as you don't want to stash a stubbed function)
const _originalDoc = collection.doc;

sinon.stub(collection, 'doc')
  .callsFake(function (...args) { // important! `function` not arrow function
    // In this function, `this` is an instance of CollectionReference
    return args.length = 0 || args[0] === undefined // don't forget the return
      ? mock.call(this)                // call the mocked function
      : _originalDoc.apply(this, args) // call the original with the original arguments
  });

如果您的模拟也调用collection.doc(),请确保调用的是原始函数,而不是存根函数(除非有意)。

318