如何为速度模板编写单元测试?
Posted
技术标签:
【中文标题】如何为速度模板编写单元测试?【英文标题】:How can I write unit tests for velocity templates? 【发布时间】:2019-11-28 15:56:50 【问题描述】:这可能吗?
朋友们好。 我正在使用 AWS AppSync + DynamoDB 构建应用程序,并且我开始拥有大量 resolver mapping templates,所有这些都是使用 Apache Velocity 模板语言 (VTL) 编写的。
我开始担心的是,这些 vtl 文件对应用程序非常重要(因为它们定义了如何检索数据)并且其中一个可能造成严重破坏的错误。所以就像系统的任何关键部分一样......我想为他们编写一些自动化的单元测试。但我没有发现很多其他人这样做。
-
如果您使用 VTL(与 AppSync 或 API 网关),您如何测试它们?
甚至可以为速度模板编写自动化测试吗?
还是我走错了路,我应该只使用 Lambda 作为解析器?
提前致谢!
【问题讨论】:
我不太明白你的问题,你有速度模板没问题,但你想测试什么? AWS AppSync 上下文中的速度模板可以包含有关如何与 DynamoDB 交互的逻辑 - 要读取的内容、要应用的过滤器值、如何插入数据等 - 它基本上是在构建查询。 这里有一个例子(虽然可能相当极端),它可以变得多么复杂:docs.aws.amazon.com/appsync/latest/devguide/… 输出仍然是一个简单的文件吗?如果是这样,您可以编写您的测试,带有输入和预期的输出文件。您使用输入处理模板并将生成的文件与预期的文件进行比较 作为单元测试是的,这就是我为邮件模板所做的事情 【参考方案1】:我自己花了一段时间才弄清楚这一点,但我找到了一种为我的 VTL 请求和响应模板编写单元测试的好方法。我使用了amplify-appsync-simulator
npm 包的 VelocityTemplate 类。到目前为止,我看到的唯一警告是您需要在 VTL 中使用 $context
,模拟器 VTL 渲染器无法识别缩写的 $ctx
。看看吧:
我的 VTL:
#set( $timeNow = $util.time.nowEpochMilliSeconds() )
"version" : "2018-05-29",
"operation" : "PutItem",
"key":
"pk" : "S" : "game#$util.autoId()" ,
"sk" : "S" : "meta#$timeNow"
,
"attributeValues" :
"players": "L" : [
"M" :
## num and color added at start game
"player": $util.dynamodb.toDynamoDBJson($context.args.input.player)
],
"createdBy": "S": "$context.identity.sub",
"gsipk": "S": "$context.args.input.status",
"gsisk": "S": "$context.args.input.level#$context.args.input.maxPlayers",
"gsipk2": "S": "game",
"turns": "L": [] ,
"nextPlayerNum": "N": 1 ,
"createdAt": "N": $timeNow ,
"updatedAt": "N": $timeNow
我的测试:
import AmplifyAppSyncSimulator from 'amplify-appsync-simulator'
import VelocityTemplate from "amplify-appsync-simulator/lib/velocity"
import readFileSync from 'fs'
import path from 'path';
const vtl = readFileSync(path.join(__dirname, '..', 'addGame-request-mapping-template.vtl'))
const template =
content: vtl
const velocity = new VelocityTemplate(template, new AmplifyAppSyncSimulator)
describe('valid user and request', () =>
// This is the graphql input
const validContext =
arguments:
input:
player: 'player#1234',
maxPlayers: 4,
status: 'new',
level: 7
,
source:
// This is a logged in user with a JWT
const requestContext =
requestAuthorizationMode: 'OPENID_CONNECT',
jwt:
sub: 'abcd1234'
const info =
fieldNodes: []
it('works', () =>
const result = velocity.render(validContext, requestContext, info)
expect(result).toEqual(
result:
version: "2018-05-29",
operation: "PutItem",
key:
pk: S: expect.stringMatching(/^game#[a-f0-9-]*$/) ,
sk: S: expect.stringMatching(/^meta#[0-9]*$/)
,
attributeValues:
players:
L: [
M: player: S: validContext.arguments.input.player
]
,
createdBy: S: requestContext.jwt.sub ,
gsipk: S: validContext.arguments.input.status ,
gsisk: S: `$validContext.arguments.input.level#$validContext.arguments.input.maxPlayers`,
gsipk2: S: 'game' ,
turns: L: [] ,
nextPlayerNum: N: 1 ,
createdAt: N: expect.any(Number) ,
updatedAt: N: expect.any(Number)
,
stash: ,
errors: [],
isReturn: false
)
)
)
【讨论】:
【参考方案2】:发现这个项目https://github.com/ToQoz/api-gateway-mapping-template有点旧但仍然有效。
它旨在测试 API Gateway 映射模板,因此它缺少您使用 AppSync 解析器获得的所有特殊 $util
功能,但我认为可以逐步添加缺少的实用程序。
【讨论】:
【参考方案3】:Amplify 刚刚发布了本地测试 AppSync api 的功能,包括 VTL 解析器。您可以查看他们的博客文章 https://aws.amazon.com/blogs/aws/new-local-mocking-and-testing-with-the-amplify-cli/,其中包含本地 API 模拟功能的操作方法;查找“当我编辑 VTL 模板时,Amplify CLI 会立即识别出来,并为解析器生成更新的代码”的位置。然后,您可以将其构建到您选择的 CI 或其他测试管道中。
【讨论】:
以上是关于如何为速度模板编写单元测试?的主要内容,如果未能解决你的问题,请参考以下文章