【问题标题】:Cannot mock admin.firestore() during unit tests在单元测试期间无法模拟 admin.firestore()
【发布时间】:2018-06-16 18:24:57
【问题描述】:

我正在阅读 how to mock google cloud functions for firebase 并且遇到了正确模拟以下代码的问题:

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();

链接中的示例使用以下代码模拟 initializeApp 确实有效

admin = require('firebase-admin');
adminInitStub = sinon.stub(admin, 'initializeApp');

现在 admin.firestore 在 firebase-namespace.js 中定义如下:

Object.defineProperty(FirebaseNamespace.prototype, "firestore", {
    get: function () {
        var ns = this;
        var fn = function (app) {
            return ns.ensureApp(app).firestore();
        };
        return Object.assign(fn, require('@google-cloud/firestore'));
    },
    enumerable: true,
    configurable: true
});

我尝试了各种方法来解决这个问题,但我失败了

  1. firestore is not a function 中的结果:

        Object.defineProperty(admin, "firestore", {
            get: function () {
                return 32;
            }
        });
    
  2. 根本不模拟 firestore() 并调用难以失败的原始函数:

        sinon.stub(admin, 'firestore').returns({get() { }});
    
  3. TypeError:无法存根不存在的自己的属性获取

       firestoreStub = sinon.stub(admin.firestore, 'get').callsFake(function () {return {data:"Foo"}});
    

我不了解admin.firebase() 究竟是什么。它看起来不像是一个属性,因为 AFAI 当我模拟一个属性的 getter 时,我会调用 admin.firebase 而不是函数 admin.firebase()。但它也不能通过函数来​​模拟。

【问题讨论】:

    标签: javascript unit-testing google-cloud-firestore sinon firebase-admin


    【解决方案1】:

    这真的花了我太长时间。

    为了能够模拟admin.firebase(),属性的getter 函数实际上应该返回一个函数。

    我最初的假设是firebase() 是一个函数,但事实并非如此。然后通过查看实现,我了解到这是一个带有自定义 getter 的属性。但是我尝试通过 getter 返回一些 json 数据块。

    我最初不明白 admin.firestore 确实是一个属性,但我错过了为什么我必须将属性调用为函数的关键,而属性本身通常不需要。

    说到点子上,我明白了属性的getter实际上返回了一个函数,admin.firebase() 可以这样读

    var method = admin.firebase; // calling the property getter function
    method(); // assuming the getter returned a function object
    

    所以对于我未来的自己来说;)这就是诀窍:

    sinon.stub(admin, 'firestore')
       .get(function() { 
           return function() { 
               return "data";
           }
       });
    

    原来我是想这么做的

    sinon.stub(admin, 'firestore').get( function () { return "data"; } ); 失败,因为 admin.firestore() 最终在 "data"() 中产生,这没有任何意义。

    【讨论】:

    • 感谢您发布此信息,塞缪尔。我也即将弄清楚如何模拟 Firestore 查询?祝我好运
    • @KyleHotchkiss 祝你好运:)。我将尽可能多的 js 代码提取到外部模块中,并尽可能使用 mocha 和 sinon 进行测试。我的场景中剩下的东西仍然是 100 多行 firestore 函数的模拟代码,因为我的云函数会读取各种文档,然后在事务中创建各种文档,用 chai 等模拟具有不同返回值的整个嵌套承诺是一个痛苦下边地区。
    • 我尝试实现你的存根,代码如下:const users = await firestore.collection('users').get();,像这样:const firestoreStub = sinon.stub(); Object.defineProperty(admin, 'firestore', { get: () => { return { collection: (path) => Promise.resolve({mocka: 'user'}) } } });,但没有帮助。知道怎么做吗?
    • @DauleDK 不是真的,我建议发布一个新帖子,以便更好地阅读并链接两者,以便其他人和我可以查看它。也可能相关:从现在到我的 post firestore 已经升级到 1.0 并更改了他们的 API,我还没有时间在我的代码中采用新的 API。
    • 请注意,如果您执行这种存根操作,您将破坏功能:test.firestore.makeDocumentSnapshot()。
    猜你喜欢
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2021-10-28
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多