问题描述
我正在为 slack bolt 应用的事件处理程序编写一些测试。昨天我为我所有的事件处理程序编写了一整套测试,这些测试都完美通过,生活非常美好。然后,我进行了一些重构,现在我的整个套件甚至无法运行,而我只看到错误提示 firebase 无法初始化。
Firebase 初始化失败,因为 jest 没有正确初始化 firebase 所需的环境变量。但是,我当然不希望它初始化。而昨天,它不是。所以我试图弄清楚为什么它现在在运行测试时尝试初始化 firebase,而以前似乎没有。
我拥有的最简单的测试,在 Events.test.ts
中只是测试 handleBlockActions
中的 Events.ts
函数,它只是确认一个松弛事件。这个测试工作得非常好,直到有一个函数 Event.ts
进行数据库调用。甚至认为我没有将 handleTeamRename
导入 Events.test.ts
,如果我在 Events.ts
中有该函数,则测试失败并显示如下 firebase 消息。如果我注释掉调用 updateOrganizationName
的行,则测试通过。
我不明白为什么只有具有一个函数来调用我从别的东西导入的文件中的数据库,就足以使我的测试由于firebase而失败未能正确初始化。
我试图制作一个最小的例子;原始文件中有更多功能,但我已经复制并删除了所有我可以用最少的代码量重现问题的内容。
如果有人能帮助我理解 jest 正在做什么,尽管据我所知,我没有要求它尝试初始化 firebase 的原因,以及我如何更好地处理这种情况,我将不胜感激。
我能找到的大多数其他答案都是关于更普遍地模拟 firebase 的,如果我现在可以的话,我想避免这种情况 - 鉴于它昨天似乎有效,这似乎是可能的?
文件结构
- database
- Organizations.ts
- Slack.ts
- firebase.ts
- services
- Events.test.ts
- Events.ts
// Events.ts
import { AckFn,DialogValidation,SayArguments } from "@slack/bolt";
import { updateOrganizationName } from "../database/Organizations";
import { getSlackTeam } from "../database/Slack";
export type AckFnSig =
| AckFn<void>
| AckFn<string | SayArguments>
| AckFn<DialogValidation>;
/**
* A user renames the organization name in slack
*/
export const handleTeamRename = async (
userId: string,token: string
): Promise<void> => {
try {
const team = await getSlackTeam(token,userId);
// if I comment out this line,the test passes
await updateOrganizationName(team.id,team.name,team.icon.image_230);
} catch (e) {
console.error("team_rename event");
console.error(e);
}
};
/**
* AckNowledge user clicking on action button
*/
export const handleBlockActions = async (ack: AckFnSig): Promise<void> => {
try {
ack();
} catch (e) {
console.error("action_link_accounts event");
console.error(e);
}
};
// Events.test.ts
import { AckFnSig,handleBlockActions } from "./Events";
describe("events",() => {
describe("handleBlockActions",() => {
it("should ack block actions",async () => {
const mockAck = jest.fn();
void (await handleBlockActions(
(mockAck as unkNown) as AckFnSig
));
await expect(mockAck).toHaveBeenCalledTimes(1);
});
});
});
FAIL src/services/Events.test.ts
● Test suite Failed to run
Service account object must contain a string "project_id" property.
8 | admin.initializeApp({
9 | // current required type appears to be wrong so has to be cast as any
> 10 | credential: admin.credential.cert(firebaseServiceKey as any),| ^
11 | databaseURL:
12 | process.env.FIREBASE_URL || "[my firebase url]",13 | });
at FirebaseAppError.FirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:44:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (node_modules/firebase-admin/lib/utils/error.js:90:28)
at new FirebaseAppError (node_modules/firebase-admin/lib/utils/error.js:125:28)
at new ServiceAccount (node_modules/firebase-admin/lib/credential/credential-internal.js:134:19)
at new ServiceAccountCredential (node_modules/firebase-admin/lib/credential/credential-internal.js:68:15)
at Object.<anonymous>.exports.cert (node_modules/firebase-admin/lib/credential/credential.js:34:54)
at Object.<anonymous> (src/database/firebase.ts:10:32)
解决方法
这在昨天有效,因为事件处理程序曾经位于从 app
导入 index.ts
的文件中。这个文件加载了 env
,因此 jest 能够初始化 firebase - 尽管我不认为它是 - 所以它没有抱怨任何数据库功能。
所以,为了解决这个问题,我将着眼于更好地处理我的 env vars,然后考虑正确地模拟 firebase。