gpt4 book ai didi

unit-testing - 对 Firebase : what's the "right way" to test/mock `transaction` s with sinon. js 的 Cloud Functions 进行单元测试

转载 作者:行者123 更新时间:2023-12-04 22:42:10 28 4
gpt4 key购买 nike

伙计,这个 firebase 单元测试真的让我大吃一惊。

我经历过the documentation并通读他们提供的示例,并对我的一些更基本的 Firebase 函数进行了单元测试,但我一直遇到问题,我不确定如何验证 transactionUpdated传递给引用的函数 .transaction正在正确更新 current目的。

他们的 child-count sample code 可能最能说明我的挣扎以及我为它编写单元测试的一次糟糕尝试。

假设我要进行单元测试的函数执行以下操作(直接取自上述链接):

// count.js
exports.countlikechange = functions.database.ref('/posts/{postid}/likes/{likeid}').onWrite(event => {
const collectionRef = event.data.ref.parent;
const countRef = collectionRef.parent.child('likes_count');

// ANNOTATION: I want to verify the `current` value is incremented
return countRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
return (current || 0) + 1;
}
else if (!event.data.exists() && event.data.previous.exists()) {
return (current || 0) - 1;
}
}).then(() => {
console.log('Counter updated.');
});
});

单元测试代码:
const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
const assert = chai.assert;
const sinon = require('sinon');

describe('Cloud Functions', () => {
let myFunctions, functions;

before(() => {
functions = require('firebase-functions');
myFunctions = require('../count.js');
});

describe('countlikechange', () => {
it('should increase /posts/{postid}/likes/likes_count', () => {
const event = {
// DeltaSnapshot(app: firebase.app.App, adminApp: firebase.app.App, data: any, delta: any, path?: string);
data: new functions.database.DeltaSnapshot(null, null, null, true)
}

const startingValue = 11
const expectedValue = 12

// Below code is misunderstood piece. How do I pass along `startingValue` to the callback param of transaction
// in the `countlikechange` function, and spy on the return value to assert that it is equal to `expectedValue`?
// `yield` is almost definitely not the right thing to do, but I'm not quite sure where to go.
// How can I go about "spying" on the result of a stub,
// since the stub replaces the original function?
// I suspect that `sinon.spy()` has something to do with the answer, but when I try to pass along `sinon.spy()` as the yields arg, i get errors and the `spy.firstCall` is always null.
const transactionStub = sinon.stub().yields(startingValue).returns(Promise.resolve(true))

const childStub = sinon.stub().withArgs('likes_count').returns({
transaction: transactionStub
})
const refStub = sinon.stub().returns({ parent: { child: childStub }})

Object.defineProperty(event.data, 'ref', { get: refStub })

assert.eventually.equals(myFunctions.countlikechange(event), true)
})
})
})

我用我的问题注释了上面的源代码,但我会在这里重申。

我如何验证 transactionUpdate callback ,传递给交易 stub ,将带上我的 startingValue并将其变异为 expectedValue然后让我观察这种变化并断言它发生了。

这可能是一个非常简单的问题,有一个明显的解决方案,但我对测试 JS 代码非常陌生,因为所有东西都必须被 stub ,所以它有点学习曲线......感谢任何帮助。

最佳答案

我同意 Firebase 生态系统中的单元测试并不像我们希望的那么容易。团队意识到这一点,我们正在努力让事情变得更好!幸运的是,现在有一些很好的方法可供您使用!

我建议看看this Cloud Functions demo我们刚刚发布的。在那个例子中,我们使用 TypeScript,但这也适用于 JavaScript。

src您会注意到我们已将逻辑拆分为三个文件:index.ts有入口逻辑,saythat.ts有我们的主要业务逻辑,和 db.ts是一个围绕 Firebase 实时数据库的薄抽象层。我们只进行单元测试 saythat.ts ;我们有意保留了 index.tsdb.ts真的很简单。

spec我们有单元测试的目录;看看index.spec.ts .您正在寻找的技巧:我们 use mock-require模拟整个 src/db.ts文件并将其替换为 spec/fake-db.ts .我们现在将执行的操作存储在内存中,而不是写入真正的数据库,我们的单元测试可以在其中检查它们是否正确。一个具体的例子是我们的 score字段,即 updated in a transaction .来自 mocking数据库,我们用来检查是否正确完成的单元测试是 a single line of code .

希望对你的测试有所帮助!

关于unit-testing - 对 Firebase : what's the "right way" to test/mock `transaction` s with sinon. js 的 Cloud Functions 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44055553/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com