如何在测试中获取 serverless.yml 中定义的环境变量
How to get environment variables defined in serverless.yml in tests
我正在为 AWS 上的 运行 lambda 函数使用无服务器框架。
在我的 serverless.yml
中有从 SSM 获取的环境变量。
当我为代码编写集成测试时,我需要代码具有环境变量,但我找不到执行此操作的好方法。
我不想为了测试而复制所有变量定义,它们已经在 serverless.yml 中定义了。另外,有些是秘密,我无法将它们提交给源代码控制,因此我还必须在 ci 环境中重复它们。
尝试使用 serverless-jest-plugin
但它无法正常工作且维护不善。
我对解决方案的想法:
- 执行测试
sls invoke
- 这会起作用,但意味着无法调试代码,我不知道测试覆盖率,而且会很慢。
- 我自己解析
serverless.yml
并导出 env 变量 - 可能但重写为测试拉动 SSM 变量的逻辑似乎是错误的。
有什么想法吗?
您是要进行模拟单元测试,还是更像是集成测试?
在第一种情况下,您不需要环境变量的实际值。模拟您的数据库,或任何需要设置环境变量的东西。这实际上是更好的方法,因为使用适当的模拟,测试将 运行 超级快。
如果您真的想使用 end-to-end/integration 种方法,那么您会做类似 sls invoke
的事情,但开玩笑地使用 javascript。因此,就像对您部署的 api.
的常规网络调用一样
此外,我建议不要将密钥存储在 serverless.yml
中。请尝试使用 secret: ${env:MY_SECRET}
语法 (https://serverless.com/framework/docs/providers/aws/guide/variables#referencing-environment-variables),并改用环境变量。如果你有一个 ci/cd 构建服务器,你可以在那里存储你的秘密。
我们最终使用的解决方案是一个名为 serverless-export-env 的无服务器插件。
添加此插件后,您可以运行 serverless export-env
将所有已解析的环境变量导出到.env
文件。这可以正确解析 ssm 参数并使我们的集成测试更加简单。
顺便说一句,要从 .env
文件中获取环境变量集,请使用 dotenv npm 包。
感谢 grishezz 找到解决方案
您可以 运行 带有 --require
选项的节点将 .env
文件注入无服务器命令。
- 使用
package.json
在项目根目录创建.env
,并在.env
中列出变量。
- 通过
yarn add -D serverless dotenv
在项目中安装serverless和dotenv。
- 运行 像
node -r dotenv/config ./node_modules/.bin/sls invoke
. 这样的命令
然后,您可以在处理程序中获取环境变量process.env.XXX
。
搜索后我做了我的自定义解决方案
import * as data from './secrets.[stage].json'
if( process.env.NODE_ENV === 'test'){
process.env = Object.assign( data, process.env );
}
//'data' is the object that has the Serverless environment variables
在我的案例中,SLS 环境变量位于文件 secrets.[stage].json
Serverless.yml 有
custom:
secrets: ${file(secrets.[stage].json)}
我正在为 AWS 上的 运行 lambda 函数使用无服务器框架。
在我的 serverless.yml
中有从 SSM 获取的环境变量。
当我为代码编写集成测试时,我需要代码具有环境变量,但我找不到执行此操作的好方法。
我不想为了测试而复制所有变量定义,它们已经在 serverless.yml 中定义了。另外,有些是秘密,我无法将它们提交给源代码控制,因此我还必须在 ci 环境中重复它们。
尝试使用 serverless-jest-plugin
但它无法正常工作且维护不善。
我对解决方案的想法:
- 执行测试
sls invoke
- 这会起作用,但意味着无法调试代码,我不知道测试覆盖率,而且会很慢。 - 我自己解析
serverless.yml
并导出 env 变量 - 可能但重写为测试拉动 SSM 变量的逻辑似乎是错误的。
有什么想法吗?
您是要进行模拟单元测试,还是更像是集成测试?
在第一种情况下,您不需要环境变量的实际值。模拟您的数据库,或任何需要设置环境变量的东西。这实际上是更好的方法,因为使用适当的模拟,测试将 运行 超级快。
如果您真的想使用 end-to-end/integration 种方法,那么您会做类似 sls invoke
的事情,但开玩笑地使用 javascript。因此,就像对您部署的 api.
此外,我建议不要将密钥存储在 serverless.yml
中。请尝试使用 secret: ${env:MY_SECRET}
语法 (https://serverless.com/framework/docs/providers/aws/guide/variables#referencing-environment-variables),并改用环境变量。如果你有一个 ci/cd 构建服务器,你可以在那里存储你的秘密。
我们最终使用的解决方案是一个名为 serverless-export-env 的无服务器插件。
添加此插件后,您可以运行 serverless export-env
将所有已解析的环境变量导出到.env
文件。这可以正确解析 ssm 参数并使我们的集成测试更加简单。
顺便说一句,要从 .env
文件中获取环境变量集,请使用 dotenv npm 包。
感谢 grishezz 找到解决方案
您可以 运行 带有 --require
选项的节点将 .env
文件注入无服务器命令。
- 使用
package.json
在项目根目录创建.env
,并在.env
中列出变量。 - 通过
yarn add -D serverless dotenv
在项目中安装serverless和dotenv。 - 运行 像
node -r dotenv/config ./node_modules/.bin/sls invoke
. 这样的命令
然后,您可以在处理程序中获取环境变量process.env.XXX
。
搜索后我做了我的自定义解决方案
import * as data from './secrets.[stage].json'
if( process.env.NODE_ENV === 'test'){
process.env = Object.assign( data, process.env );
}
//'data' is the object that has the Serverless environment variables
在我的案例中,SLS 环境变量位于文件 secrets.[stage].json
Serverless.yml 有
custom:
secrets: ${file(secrets.[stage].json)}