Front-End Web & Mobile
Introducing template evaluation and unit testing for AWS AppSync resolvers
AWS AppSync is a managed serverless GraphQL service that simplifies application development by letting you create a flexible API to securely access, manipulate, and combine data from one or more data sources with a single network call.
In GraphQL, developers write resolvers, units of code that implement the business logic that controls how to fetch data from data sources. Resolvers provide the runtime to fulfill GraphQL such as queries, mutations, or subscriptions with the right data.
AWS AppSync leverages Apache VTL (Velocity Template Language) to provide a lean and fast compute layer to resolve GraphQL fields. This enables developers to customize the behavior, as well as apply logic and conditions before and after communicating with the data source. AWS AppSync provides flexible integrated VTL utilities that allow developers to parse (e.g., $util.parseJson
), convert (e.g., $util.toJson
), generate (e.g., $util.autoId
and $util.autoUlid
), and log data (e.g., $util.log
). AWS AppSync lets developers write all of their business logic using VTL in resolvers, as well as use Direct Lambda Resolvers, where they bypass VTL and use AWS Lambda functions to write their business logic directly.
Today, we’re releasing a new API command for AWS AppSync, EvaluateMappingTemplate, that allows customers to evaluate their AWS AppSync resolver and AWS AppSync function mapping templates. Evaluating a mapping template lets you use mock data to see how both the request and the response templates evaluate without actually running against a data source. Previously, this functionality was only available in the AWS AppSync console. Developers can now access this functionality remotely by using the latest version of the AWS Command Line Interface (AWS CLI), or by using the latest version of the AWS SDKs. Developers can leverage the EvaluateMappingTemplate command to write unit tests that verify the behavior of their resolvers in their favorite testing frameworks.
In this post, we cover the three main approaches that EvaluateMappingTemplate can be used to verify the behavior of your resolver, from both the AWS Console and your local environment. We also cover how these tests can be integrated with test suites like Jest Testing Framework.
Architecture
Example application overview
To illustrate the testing of resolvers, we use a simple Task API in AWS AppSync. This is a basic AWS AppSync API for creating calendar events with user comments.
Go to the AWS AppSync Console and create a new API with the console wizard using the Tasks App sample project. Give your API a name, such as Tasks API, and select Create. An AWS CloudFormation template is deployed in your account with a pre-confirmed AWS AppSync GraphQL API, an Amazon Cognito user pool associated with it, and a linked Amazon DynamoDB table to store data.
Create the necessary users in the Cognito user pool to interact with the Tasks API. Refer to the Cognito documentation for more information on how to create users.
Now we’ll add some business logic to the resolvers. Back at the AWS AppSync Console, select the Schema section on the left navigation menu. On the right side, under Resolvers, search for Mutation and choose TaskDynamoDataSource pointing to to createTask(…): Task Mutation.
In this case, we’ll add a conditional check to evaluate the description field. If the user supplies a description field value during the input, then the logic retains the user input – if not, then the logic concatenates the title, status, and department fields to create a new description.
Leave the default Response Mapping Template as is, replace the Request Mapping Template with the following snippet, and select Save Resolver at the top of the page.
Unit testing the AWS AppSync Resolvers
There are three ways that you can unit test the resolver logic with mock data without having the resolver communicate with the actual data source.
Prerequisites
The AWS Identity and Access Management (IAM) user or role used in the tests should require the following permission to execute the EvaluateMappingTemplate command.
First approach – AWS Console
The AWS AppSync console provides tools to create a GraphQL request and response with mock data, as well as test the resolver visually.
When a GraphQL resolver is invoked, it contains a context object that has relevant information about the request for you to program against. This includes arguments from a client, identity information, and data from the parent GraphQL field. It also has results that are made available to the response template. When writing or editing a resolver function, you can pass a mock context object in the console editor. This enables you to see how both the request and the response templates evaluate without actually running against a data source.
In the AWS AppSync console, again click on the createTask(…): Task Mutation. At the top of the page, choose Select test context, and choose Create new context. In the Configure test context, select Context with Cognito User Pools Auth, and then enter a name.
Replace the Execution context with the following snippet and select Save. The purpose of the following test is to verify whether or not the description field in the result contains a concatenated string of title, status, and department fields when the description field in the input is empty or not present.
To evaluate your resolver using this mocked context object, choose Run Test. In the Evaluated request mapping template section, you can observe that the test executed successfully and the description is a concatenated string of title, department, and status as specified in the Request mapping template logic.
Running this test lets you verify the logic in the resolver via the AWS AppSync Console.
Second approach – AWS CLI
We’ll use the new API EvaluateMappingTemplate to remotely test a mapping template with mock data.
Prerequisites
Install and configure the latest version of the AWS CLI.
Testing with the API
We’ll test the same context and mapping that we used in the first approach. In your local computer, save the request template to a file named template.vtl, and save the context objects as context.json.
Execute the following command in the command prompt:
aws appsync evaluate-mapping-template —template file:// template.vtl —context file://context.json
You get the following response:
The evaluation result contains the evaluated request mapping template. In this above result, the description field is a concatenation of title, status, and department, which is the expected behavior from the Resolver logic. This means that you can unit test your resolver logic from your local workstation via the AWS AppSync APIs.
Third approach – AWS SDK
We’re also introducing the EvaluateMappingTemplate method in the AWS SDK to remotely test your mapping templates with mocking data, as well as integrate with your preferred testing frameworks.
Prerequisites
Utilize the following prerequisites:
- Install and configure AWS SDK V2.
- Install NodeJs runtime
- We test the same context and mapping that we used in the first approach using AWS SDK for Javascript.
Save the following snippet as index.js in your local workstation.
Execute the following command in the command prompt. Try with both of the context files and compare the results.
With the AWS SDK, you can easily incorporate tests in your favorite test suite to validate your template behavior. For example, you can create a test by leveraging the Jest testing framework:
Prerequisites
Utilize the following prerequisites to follow along:
- Install and configure AWS SDK V2.
- Install and configure Jest package
- Set up a new npm local project with
npm init –yes
- Install jest with npm
- install jest
npm install jest
- Add the following command to the package.json
We’ll test the same context and mapping that we used in the first approach using AWS SDK for Javascript.
Save the following snippet as resolver.test.js in your local workstation:
Execute the following command in the command prompt:
Cleanup
In the AWS CloudFormation console, delete the stack generated by the AppSync console wizard to remove all generated AWS resources.
Conclusion
Unit testing provides a mechanism for testing individual units of application code. Therefore, it’s helpful for quickly identifying and isolating issues. As part of your automated test suites, it can also be utilized to prevent bad code from being deployed into production. In this post, you learned about three approaches to test the AWS AppSync Resolvers without having to communicate with the backend data sources from your local workstation. You also learned how you can incorporate these tests as part of automated test suites. For more information on testing and debugging AWS AppSync Resolvers, refer to the AWS AppSync documentation.
Authors: