如何为速度模板编写单元测试?

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 或其他测试管道中。

【讨论】:

以上是关于如何为速度模板编写单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何为@KafkaListener 编写单元测试?

如何为 UserDefaults 编写单元测试

如何为 Python socketserver 请求处理程序编写单元测试?

如何为 angular2 的登录组件编写测试(单元测试)

如何为 JWT 策略编写单元测试用例

如何为以下代码段编写单元测试用例