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

cloud function unit test mock new document ID

对于 Firestore 云函数 TypeScript 单元测试,我想模拟 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 函数只接受一个路径参数,但您应该养成使用剩余参数的习惯,以确保您处理所有参数。

// 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
  });

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