微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在测试套件中运行时,云功能中的事务中的数据始终为空

如何解决在测试套件中运行时,云功能中的事务中的数据始终为空

我有一个Firebase云功能可以做到这一点:

const admin = require('firebase-admin')
admin.initializeApp()

exports.setSessionState = functions.https.onCall(async (data,context) => {
    const stateId = data.stateId
    const details = data.details
    const stateRef = admin.database().ref(`state/${stateId}`)
    stateRef.transaction((state) => {
        if (state) {
            state.details = details
        }
        return state
    })
})

代码在实际的应用程序中运行良好,并且状态已更新,但是在状态始终为null的测试中运行时,我遇到了问题。 (换句话说,永远不会设置细节。)该测试使用Mocha框架,并且在一个真实的Firebase项目上运行,我看不到这里会有什么不同,但是当从客户端应用程序以及从测试套件中调用它时:

const chai = require('chai')
const assert = chai.assert

const test = require('firebase-functions-test')({
  databaseURL: '<redacted>',storageBucket: '<redacted>',projectId: '<redacted>',},'../service-account-credentials.json')

describe('CFsetSessionState',() => {
  let wrapped
  let cloudFunctions
  let admin

  before(() => {
    cloudFunctions = require('../index')
    admin = require('firebase-admin')
    wrapped = test.wrap(cloudFunctions.CFsetSessionState)
  })

  it('Test setting state',async () => {
    const stateId = 'abc'

    const data = {
      stateId: stateId,details: {
        name: 'New name'
      }
    }

    const context = {
      auth: {
        uid: 123
      }
    }

    const stateRef = admin.database().ref(`state/${stateId}`)

    await stateRef.set({
      name: 'PrevIoUs name',active: true
    })

    await wrapped(data,context)

    const snapshot = await stateRef.once('value')
    const state = snapshot.val()

    // Details do not exist here,why?
    assert.equal(state.details.name,'New name')
  })
})

在测试之后,我将数据库状态保持不变,因此我可以看到状态对象中确实存在数据,但是未设置详细信息。在调用云函数之前和之后进行一些设置和获取数据的实验(使用.once()可以改变行为,使我认为这可能是一些缓存问题,但是这种实验并没有给我任何特别的稳定性结束状态。我不知道等效的本地缓存在云功能中如何工作,它目前显示随机行为。

是什么原因造成的?

解决方法

我还没有尝试过通过测试运行您的Cloud Function,但是很可能是由于您错误地管理Cloud Function的生命周期这一事实造成的。由于它是可调用的,因此您需要通过返回Promise(或所有异步工作完成时的值)来终止它。文档中的更多详细信息herehere

因此,您应该按照以下方式调整CF:

exports.setSessionState = functions.https.onCall(async (data,context) => {
    const stateId = data.stateId
    const details = data.details
    const stateRef = admin.database().ref(`state/${stateId}`)
    return stateRef.transaction((state) => {   // Note the return here
        if (state) {
            state.details = details
        }
        return state
    })
})

我们将返回Promise返回的Transaction

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?