gpt4 book ai didi

node.js - 使用 Jest 测试 firebase 函数时的 Flakey 测试

转载 作者:行者123 更新时间:2023-12-05 06:04:18 29 4
gpt4 key购买 nike

我正在使用 Jest 和模拟器测试 Firebase 函数,尽管这些测试可能来自竞争条件。所谓 flakey,我的意思是有时它们会通过,有时不会,即使在同一台机器上也是如此。

测试和函数是用 TypeScript 编写的,然后用 babel 转译。

示例测试/功能

注意:这只是其中一个 flakey 测试的示例。许多其他测试都是古怪的。解决方案最好不仅能解决这个案例,还能解决一般问题。

测试

import { onProfilesWrite } from '../src/profiles/on-write'
import { initializeAdminApp } from '@firebase/rules-unit-testing'

const admin = initializeAdminApp({ projectId: 'projectId' }).firestore()

const wrappedFunction = testEnvironment.wrap(onProfilesWrite)

const profilePath = `profiles/${uid}`

const customerProfile = {
roles: ['customer'],
slug: 'slug',
image: 'image.png',
fullName: 'John Smith',
}

const publisherRoles = ['customer', 'publisher']

const publisherProfile = {
...customerProfile,
roles: publisherRoles,
}

const createChange = async (
before: Record<string, unknown> | undefined,
changes: Record<string, unknown>
) => {
const publisherStatsRef = admin.doc(profilePath)
if (before) await publisherStatsRef.set(before)

const beforeSnapshot = await publisherStatsRef.get()
await publisherStatsRef.set(changes, { merge: true })

const afterSnapshot = await publisherStatsRef.get()

return testEnvironment.makeChange(beforeSnapshot, afterSnapshot)
}

test('If user profile is created as a publisher, publisherDetails is created', async () => {
const change = await createChange(undefined, publisherProfile)
await wrappedFunction(change)
const snapshot = await admin.doc(`profileDetails/${uid}`).get()
const data = snapshot.data()
expect(data).toBeTruthy()
expect(data?.id).toBeTruthy()
expect(data?.slug).toBe(publisherProfile.slug)
expect(data?.profileImage).toBe(publisherProfile.image)
expect(data?.publisherName).toBe(publisherProfile.fullName)
expect(data?.music).toMatchObject([])
})

运行测试

firebase emulators:exec \"jest functions/__tests__ --detectOpenHandles\" --only firestore

输出

If user profile is created as a publisher, publisherDetails is created

expect(received).toBeTruthy()

Received: undefined

46 | const snapshot = await admin.doc(`profileDetails/${uid}`).get()
47 | const data = snapshot.data()
> 48 | expect(data).toBeTruthy()
| ^
49 | expect(data?.id).toBeTruthy()
50 | expect(data?.slug).toBe(publisherProfile.slug)
51 | expect(data?.profileImage).toBe(publisherProfile.image)

函数

import * as functions from 'firebase-functions'

// initializes the admin app, then exports admin.firestore
import { firestore } from '../admin'

const database = firestore()

const createPublisherId = async (): Promise<string> => {
let id = ''
const MAX_NUMBER = 1000000
while (id === '') {
const temporaryId = String(Math.ceil(Math.random() * MAX_NUMBER))
const snapshot = await firestore()
.collection('publisherDetails')
.where('sku', '==', temporaryId)
.limit(1)
.get()
if (snapshot.empty) id = temporaryId
}
return id
}

export const createPublisherDetails = async (
newData: firestore.DocumentData,
uid: string
): Promise<void> => {
const id = await createPublisherId()

await database.doc(`publisherDetails/${uid}`).set(
{
id,
slug: newData.slug,
publisherName: newData.fullName,
profileImage: newData.image,
music: [],
},
{ merge: true }
)
}


export const onProfilesWrite = functions.firestore.document('profiles/{uid}').onWrite(
async (change): Promise<void> => {
const { id: uid } = change.after
const oldData = change.before.data()
const newData = change.after.data()

if (
newData?.roles?.includes('publisher') &&
(typeof oldData === 'undefined' || !oldData.roles?.includes('publisher'))
)
await createPublisherDetails(newData, uid)
}
)

调试步骤

  • 所有 promise 都在云函数中等待(由 ESLint 规则确认 @typescript-eslint/no-floating-promises)
  • 还将测试转换为 Mocha(按照 Firebase 文档的建议),同样的错误
  • 将测试中的 async/await 转换为 promise.then() 语法

元数据

  • 操作系统:macOS 11.2、Ubuntu 18.04
  • 开 Jest :26.6.3
  • Firebase:8.2.6
  • Firebase 工具:9.3.0

随着评论的涌入,无论是问题还是建议,我都会继续更新这篇文章。

最佳答案

将您的测试部分更改为如下:

test('If user profile is created as a publisher, publisherDetails is created', async () => {
const change = await createChange(undefined, publisherProfile)
await wrappedFunction(change)
const documentObject = await admin.doc(`profileDetails/${uid}`)
const snapshot = await documentObject.get()
const data = snapshot.data()
expect(data).toBeTruthy()
expect(data?.id).toBeTruthy()
expect(data?.slug).toBe(publisherProfile.slug)
expect(data?.profileImage).toBe(publisherProfile.image)
expect(data?.publisherName).toBe(publisherProfile.fullName)
expect(data?.music).toMatchObject([])

})

原因是在您的测试区域中,您对 await 的使用有点不正确(正在等待的对象上的函数链接在同一调用行中是一个很大的禁忌)

关于node.js - 使用 Jest 测试 firebase 函数时的 Flakey 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66357630/

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