Reputation: 1262
Is this even possible?
Hello friends. I'm in the process of building an application using AWS AppSync + DynamoDB and I'm starting to have quite a large pile of resolver mapping templates, all which are written using the Apache Velocity Template Language (VTL).
The concern I'm starting to have is that these vtl files are quite critical to the application (since they define how data is retrieved) and a bug in one of the could wreak havoc. So like any critical part of a system... I would like to write some automated unit tests for them. But I haven't found much about others doing this.
Thanks in advance!
Upvotes: 14
Views: 5797
Reputation: 935
It took me a while to figure this out myself, but I found a good way to write unit tests for my VTL request and response templates. I used the amplify-appsync-simulator
npm package's VelocityTemplate class. The only caveat I have seen so far is that you need to use $context
in your VTL, the abbreviated $ctx
is not recognized by the simulators VTL renderer. Check it out:
My 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} }
}
}
My test:
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
})
})
})
Upvotes: 7
Reputation: 1750
Found this project https://github.com/ToQoz/api-gateway-mapping-template which is a bit old but still works.
It is designed to test API Gateway mapping templates so it is missing all the special $util
functions you get with AppSync resolvers, but I think one can incrementally add missing utils.
Upvotes: 3
Reputation: 1683
Amplify just released the ability to locally test your AppSync apis, including VTL resolvers. You can check out their blog post https://aws.amazon.com/blogs/aws/new-local-mocking-and-testing-with-the-amplify-cli/ which contains a how-to for the local API Mocking functionality; Look for where it says "When I edit a VTL template, the Amplify CLI recognizes that immediately, and generates the updated code for the resolver." You could then build this into a CI or other testing pipeline of your choosing.
Upvotes: 1