【问题标题】:sinon stub a firebase collection with chained methods for unit testing...(sinon, node/express, Jasmine)sinon 存根带有用于单元测试的链式方法的 firebase 集合...(sinon,node/express,Jasmine)
【发布时间】:2021-06-27 01:14:58
【问题描述】:

在我的 nodejs 代码中,我有一个 sn-p:

   await cfDB.collection('users').doc(userAccount.uid).set({
      email: 'email@domain.com',
      firstName: 'firstname',
      lastName: 'Lastname,
    });

我如何创建一个这样的 sinon 模拟来使用 jasmine 进行单元测试?

更完整的上下文......

 const { Firestore } = require('@google-cloud/firestore');

  const cfDB = new Firestore();

  // Create Firestore user document
  try {
    await cfDB.collection('users').doc('E7skP0IncSW7wkBxnrYFx6udzGH2').set({
      email: 'email@domain.com',
      firstName: 'Firstname',
      lastName: 'Lastname',
    });


  } catch (error) {
    res.json({ success: false, payload: { message: 'Firebase User write error. ' + error } });
    return;
  }

  // Success
  res.json({ success: true, payload: { message: 'User created.', userAccount: userAccount } });
}

【问题讨论】:

  • cfDB 是什么?显示完整、最少的代码
  • 我添加了更多上下文。
  • res 来自哪里?
  • res 是 http 响应
  • 你能展示一个最小的、完整的代码吗

标签: node.js firebase express unit-testing sinon


【解决方案1】:

我仍在努力,但我现在已经能够做到这一点:

function stubTest(path: string, result: any){
    sinon.stub(admin, 'firestore')
    .get(() => {
        return function() {
            return stubCollection(path, result);            
        }
    });
}
function stubDoc(path: string, result: any){
    const parts = path.split('/');
    const rest = parts.slice(1).join('/');
    return {
        doc: () => {
            if(rest){
                return stubCollection(rest, result);
            }else {
                return {
                    get: () => stubData(result)               
                }                
            }
        }
    }
}
function stubCollection(path: string, result: any){
    const parts = path.split('/');
    const rest = parts.slice(1).join('/');
    return {
        collection: () => {
            if(rest){
                return stubDoc(rest, result);
            }else {
                return {
                    get: () => stubData(result)
                }                
            }
        }
    }
}
function stubData(result: any){
    return {
        data: () => result
    }
}

要使用它,您只需致电stubTest("restaurants/12333/orders/123111", {mockResponse: "someData"});

这将模拟这样的调用

const order = (await firestore.collection('restaurants').doc('12333').collection('orders').doc('123111').get()).data();

ofc还有很长的路要走,添加更多mock方法但至少我不需要多次写stub

【讨论】:

    【解决方案2】:

    这里是解决方案...

            const collectionStub = sinon.stub(firebase.cfDB, 'collection')
            .get(() => {
                return function() {
                    return {
                        doc: (path) => {
                            return {
                                set: () => [{user: 'mock-user-1'}, {user: 'mock-user-2'}]
                            }
                        }
                    }
                }
            });
    

    【讨论】:

      【解决方案3】:

      您不会使用 sinon 来模拟它,而是使用 @firebase/rules-unit-testing 包来强制与 Firestore/RTDB 模拟器交互。

      【讨论】:

      • 我以为 firebase rules-unit-testing 只是为了测试安全规则???
      • @SteveGeggie 虽然这是主要目的,但为了测试安全规则,它需要能够与 Firestore 和 RTDB 交互,它使用模拟器进行交互。您可以在此处使用相同的 Firestore 和 RTDB 方法,只需跳过测试安全规则部分。
      • 你确定这是不可能用 sinon 模拟的吗?这是我们团队的标准。
      • 我并不是说这是不可能的,但我不明白为什么要针对模拟数据库而不是正确模仿真实事物并专为测试而设计的模拟器进行单元测试。
      猜你喜欢
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 2015-06-02
      相关资源
      最近更新 更多