firebase 云推送_开发者点心测试具有用户ID令牌的Firebase云功能

本文探讨了在本地环境中测试Firebase云函数的方法,特别是当函数依赖于用户ID令牌时。文章详细介绍了如何在测试套件中生成有效的用户ID令牌,以及如何通过调整云函数结构,使用onCall()替代onRequest(),从而简化测试过程,消除对用户ID令牌的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

firebase 云推送

Today I was carefully assembling local integration tests for all of the Firebase Cloud Functions within an app project. These Cloud Functions act on behalf of a specific user. This begged the question, how does one locally test a Cloud Function when that Cloud Function expects an authenticated user ID?

今天,我正在认真地为应用程序项目中的所有Firebase Cloud Functions组装本地集成测试。 这些云功能代表特定用户运行。 这就提出了一个问题,当一个Cloud Function需要一个经过身份验证的用户ID时,如何在本地测试Cloud Function?

Follow me @SuprDeclarative on Twitter

在Twitter上关注我@SuprDeclarative

Watch Flutter education on YouTube

在YouTube上观看Flutter教育

Learn Flutter at superdeclarative.com

通过superdeclarative.com了解Flutter

Imagine that you defined a cloud function to upload and configure an avatar for a given user. You’d need that user’s ID, but you’d also need to ensure that the user is the one who made the request. Otherwise you could change anybody’s avatar. This is why you would need a “user ID token”, which includes the ability to verify the identity of the user making the request.

想象一下,您定义了一个云功能来为给定用户上传和配置头像。 您需要该用户的ID,但还需要确保该用户是发出请求的用户。 否则,您可以更改任何人的头像。 这就是为什么您需要一个“用户ID令牌”的原因,其中包括验证发出请求的用户身份的能力。

The “user ID token” is typically generated in the client app using the Firebase SDK. So how does one provide a “user ID token” within a local Cloud Function test suite?

“用户ID令牌”通常是使用Firebase SDK在客户端应用中生成的。 那么,如何在本地Cloud Function测试套件中提供“用户ID令牌”?

It turns out that you can, in fact, generate a “user ID token” within a test suite, but there is no Firebase API to do this (as far as I know). I’ll describe an approach below that I found on StackOverflow.

事实证明,您实际上可以在测试套件中生成“用户ID令牌”,但是据我所知,没有Firebase API可以做到这一点。 我将在下面介绍在StackOverflow上发现的一种方法。

It also turns out that I should have been using a different part of the Firebase Cloud Functions API. I’ll explain that below, as well.

事实证明,我应该使用Firebase Cloud Functions API的其他部分。 我也会在下面解释。

First, let’s look at how I originally defined my cloud functions.

首先,让我们看看我最初是如何定义云功能的。

Second, let’s look at what you need to do to generate a legitimate “user ID token” within a test suite.

其次,让我们看看在测试套件中生成合法的“用户ID令牌”所需执行的操作。

Third, let’s look at how I changed the structure of my cloud functions to make the “user ID token” irrelevant.

第三,让我们看看如何更改云功能的结构以使“用户ID令牌”无关。

我原来的云函数定义结构 (My original cloud function definition structure)

The following is a minimal example of what my cloud functions look like. These function definitions are what is pushed to the Firebase cloud servers when you “deploy” your cloud functions.

以下是我的云功能外观的最小示例。 这些功能定义是“部署”云功能时推送到Firebase云服务器的内容。

exports.someFunction = functions.https.onRequest(async (req, res) => {
const userIdToken = req.body.userToken;
const decodedToken = await admin.auth().verifyIdToken(userIdToken);
const userId = decodedToken.uid; // Ensure the userId is legitimate and then do what you want.
});

Notice that I defined my cloud functions using the onRequest() configuration. This configuration operates with an incoming request object and an outgoing response object. Everything in an onRequest() function operates in terms of pure HTTP communication.

请注意,我使用onRequest()配置定义了云函数。 此配置与传入请求对象和传出响应对象一起运行。 onRequest()函数中的所有内容onRequest()纯HTTP通信方式运行。

如何在测试套件中生成用户ID令牌 (How to generate a user ID token in a test suite)

Given a cloud function that is defined with onRequest(), the following illustrates the fundamentals of how you would define a javascript test that begins by generating a legitimate “user ID token”.

给定使用onRequest()定义的云函数,以下内容说明了如何定义javascript测试的基础,该javascript测试首先生成合法的“用户ID令牌”。

it('does something', async () => {
// Obtain a UserRecord so that you can get a real user ID.
// This is a standard Firebase API ability.
const userRecord = await admin.auth().getUserByEmail('sometestuser@test.com');
// Create a "custom token" based on the test user.
// This is a standard Firebase API ability.
const customToken = await admin.auth().createCustomToken(userRecord.uid); // Here is the important part. Convert the "custom token" into
// a "user ID token".
//
// This line assumes the existence of a local property called
// "webApiKey" which holds your Firebase project's API key
// for a web project.
//
// Axios was a personal choice as an HTTP library.
const idTokenResponse = await axios.post(
`https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=${webApiKey}`,
{
token: customToken,
returnSecureToken: true,
},
); // Here is the "user ID token" that we worked so hard to obtain.
const userIdToken = idTokenResponse.data.idToken; // Invoke your cloud function with the userIdToken in the
// request...
});

This approach is based on the following StackOverflow post:

此方法基于以下StackOverflow帖子:

https://stackoverflow.com/questions/48268478/in-firebase-how-to-generate-an-idtoken-on-the-server-for-testing-purposes

https://stackoverflow.com/questions/48268478/in-firebase-how-to-generate-an-idtoken-on-the-server-for-testing-purposes

Using the approach above, I was able to correctly execute my cloud functions locally to verify their behavior. However, Simon Lightfoot turned me on to a slight change in structure that completely eliminated the need for a “user ID token” within my test suite altogether.

使用上述方法,我能够在本地正确执行我的云功能以验证其行为。 但是, 西蒙·莱特富特 ( Simon Lightfoot)使我开始进行结构上的细微更改,从而完全消除了我的测试套件中对“用户ID令牌”的需求。

我如何更改代码以避免测试身份验证 (How I changed my code to avoid testing authentication)

The purpose of the cloud functions that I’m writing right now are to execute actions on behalf of an authenticated user. Such functions should not be defined as onRequest() functions, but rather as onCall() functions.

我现在正在编写的云功能的目的是代表经过身份验证的用户执行操作。 此类函数不应定义为onRequest()函数,而应定义为onCall()函数。

An onCall() function is defined in a very similar manner to onRequest(), except Firebase automatically does some work on your behalf. Namely, Firebase automatically processes a “user ID token” and converts it into a “user ID”. That user ID is made available to your onCall() function within context.auth.id.

onCall()函数的定义方式与onRequest()极为相似,只是Firebase会自动代表您执行一些工作。 即,Firebase自动处理“用户ID令牌”并将其转换为“用户ID”。 该用户ID可用于context.auth.id onCall()函数。

Let’s take a look at a barebones onCall() function.

让我们看一下准系统onCall()函数。

exports.someFunction = functions.https.onCall((data, context) => {
// retrieve the user ID from the incoming context.
const userId = context.auth.id; // do whatever you want with the authenticated user's ID...
});

Because the job of processing the “user ID token” is now handled internally by Firebase, instead of manually within our function, we no longer need to validate that behavior. We want to test *our* behavior, not Firebase’s behavior. Thus, we are able to achieve the same test effectiveness with a much simpler test, as shown below:

因为处理“用户ID令牌”的工作现在由Firebase内部处理,而不是在我们的功能中手动进行,所以我们不再需要验证该行为。 我们要测试*我们的*行为,而不是Firebase的行为。 因此,我们可以通过更简单的测试来达到相同的测试效果,如下所示:

// Obtain a UserRecord so that you can get a real user ID.
// This is a standard Firebase API ability.
//
// You could also hardcode a user ID if that meets your needs.
const userRecord = await
admin.auth().getUserByEmail('sometestuser@test.com');
const userId = userRecord.uid;// Use firebase-functions-test to "wrap" our own function so
// that we can pass in fake auth data.
//
// The "test" object refers to the imported
// "firebase-functions-test" module.
const testWrappedFunction = test.wrap(someFunction);// Execute our wrapped function to test it.
await testWrappedFunction(
// This object holds your incoming parameters.
{},
// This object holds the "context" of your invocation.
{
auth: {
id: userId,
},
},
);// Verify any side effects of your function, e.g., verify that
// the data in your Firestore DB matches your expectations.

By using onCall() we have completely eliminated the need to generate and exchange tokens to verify the behavior of our cloud functions, and that change did not cost us anything in terms of how thoroughly we test our application behavior.

通过使用onCall()我们完全消除了生成和交换令牌以验证我们的云函数行为的需要,并且就彻底测试应用程序行为而言,这种更改不会给我们带来任何代价。

I hope you enjoyed today’s dev snack!

希望您喜欢今天的开发小吃!

Cloud function unit testing: https://firebase.google.com/docs/functions/unit-testing

云功能单元测试: https : //firebase.google.com/docs/functions/unit-testing

Callable functions: https://firebase.google.com/docs/functions/callable

可调用的函数: https : //firebase.google.com/docs/functions/callable

Callable functions protocol: https://firebase.google.com/docs/functions/callable-reference

可调用函数协议: https : //firebase.google.com/docs/functions/callable-reference

Firebase getUserByEmail: https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getuserbyemail

Firebase getUserByEmail: https ://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getuserbyemail

翻译自: https://medium.com/super-declarative/dev-snack-testing-firebase-cloud-functions-with-user-id-tokens-83841d3f06c

firebase 云推送

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值