AWS News Blog

New – Local Mocking and Testing with the Amplify CLI

The open source Amplify Framework provides a set of libraries, user interface (UI) components, and a command line interface (CLI) that make it easier to add sophisticated cloud features to your web or mobile apps by provisioning backend resources using AWS CloudFormation.

A comment I often get when talking with our customers, is that when you are adding new features or solving bugs, it is important to iterate as fast as possible, getting a quick feedback from your actions. How can we improve their development experience?

Well, last week the Amplify team launched the new Predictions category, to let you quickly add machine learning capabilities to your web or mobile app. Today, they are doing it again. I am very happy to share that you can now use the Amplify CLI to mock some of the most common cloud services it provides, and test your application 100% locally!

By mocking here I mean that instead of using the actual backend component, an API in the case of cloud services, a local, simplified emulation of that API is available instead. This emulation provides the basic functionality that you need for testing during development, but not the full behavior you’d get from the production service.

With this new mocking capability you can test your changes quickly, without the need of provisioning or updating the cloud resources you are using at every step. In this way, you can set up unit and integration tests that can be executed rapidly, without affecting your cloud backend. Depending on the architecture of your app, you can set up automatic testing in your CI/CD pipeline without provisioning backend resources.

This is really useful when editing AWS AppSync resolver mapping templates, written in Apache Velocity Template Language (VTL), which take your requests as input, and output a JSON document containing the instructions for the resolver. You can now have immediate feedback on your edits, and test if your resolvers work as expected without having to wait for a deployment for every update.

For this first release, the Amplify CLI can mock locally:

API Mocking
Let’s do a quick overview of what you can do. For example, let’s create a sample app that helps people store and share the location of those nice places that allow you to refill your reusable water bottle and reduce plastic waste.

To install the Amplify CLI, I need Node.js (version >= 8.11.x) and npm (version >= 5.x):

npm install -g @aws-amplify/cli
amplify configure

Amplify supports lots of different frameworks, for this example I am using React and I start with a sample app (npx requires npm >= 5.2.x):

npx create-react-app refillapp
cd refillapp

I use the Amplify CLI to inizialize the project and add an API. The Amplify CLI are interactive, asking you questions that drive the configuration of your backend. In this case, when asked, I select to add a GraphQL API.

amplify init
amplify add api

During the creation of the API, I edit the GraphQL schema, and define a RefillLocation in this way:

type RefillLocation @model {
  id: ID!
  name: String!
  description: String
  streetAddress: String!
  city: String!
  stateProvinceOrRegion: String
  zipCode: String!
  countryCode: String!
}

The fields that have an exclamation mark ! at the end are mandatory. The other fields are optional, and can be omitted when creating a new object.

The @model you see in the first line is a directive using GraphQL Transform to define top level object types in your API that are backed by DynamoDB and generate for you all the necessary CRUDL (create, read, update, delete, and list) queries and mutations, and the subscriptions to be notified of such mutations.

Now, I would normally need to run amplify push to configure and provision the backend resources required by the project (AppSync and DynamoDB in this case). But to get a quick feedback, I use the new local mocking capability running this command:

amplify mock

Alternatively, I can use the amplify mock api command to specifically mock just my GraphQL API. It would be the same at this stage, but it can be handy when using more than one mocking capability at a time.

The output of the mock command gives you some information on what it does, and what you can do, including the AppSync Mock endpoint:

GraphQL schema compiled successfully.

Edit your schema at /MyCode/refillapp/amplify/backend/api/refillapp/schema.graphql or place .graphql files in a directory at /MyCode/refillapp/amplify/backend/api/refillapp/schema

Creating table RefillLocationTable locally

Running GraphQL codegen

✔ Generated GraphQL operations successfully and saved at src/graphql

AppSync Mock endpoint is running at http://localhost:20002

I keep the mock command running in a terminal window to get feedback of possible errors in my code. For example, when I edit a VTL template, the Amplify CLI recognizes that immediately, and generates the updated code for the resolver. In case of a mistake, I get an error from the running mock command.

The AppSync Mock endpoint gives you access to:

I can now run GraphQL queries, mutations, and subscriptions locally for my API, using a web interface. For example, to create a new RefillLocation I build the mutation visually, like this:

To get the list of the RefillLocation objects in a city, I build the query using the same web interface, and run it against the local DynamoDB storage:

When I am confident that my data model is correct, I start building the frontend code of my app, editing the App.js file of my React app, and add functionalities that I can immediately test, thanks to local mocking.

To add the Amplify Framework to my app, including the React extensions, I use Yarn:

yarn add aws-amplify
yarn add aws-amplify-react

Now, using the Amplify Framework library, I can write code like this to run a GraphQL operation:

import API, { graphqlOperation } from '@aws-amplify/api';
import { createRefillLocation } from './graphql/mutations';

const refillLocation = {
  name: "My Favorite Place",
  streetAddress: "123 Here or There",
  zipCode: "12345"
  city: "Seattle",
  countryCode: "US"
};

await API.graphql(graphqlOperation(createRefillLocation, { input: refillLocation }));

Storage Mocking
I now want to add a new feature to my app, to let users upload and share pictures of a RefillLocation. To do so, I add the Storage category to the configuration of my project and select “Content” to use S3:

amplify add storage

Using the Amplify Framework library, I can now, straight from the browser, put, get, or remove objects from S3 using the following syntax:

import Storage from '@aws-amplify/storage';

Storage.put(name, file, {
  level: 'public'
})
.then(result => console.log(result))
.catch(err => console.log(err));

Storage.get(file, {
  level: 'public'
})
.then(result => {
  console.log(result);
  this.setState({ imageUrl: result });
  fetch(result);
})
.catch(err => alert(err));

All those interactions with S3 are marked as public, because I want my users to share their pictures with each other publicly, but the Amplify Framework supports different access levels, such as private, protected, and public. You can find more information on this in the File Access Levels section of the Amplify documentation.

Since S3 storage is supported by this new mocking capability, I use again amplify mock to test my whole application locally, including the backend used by my GraphQL API (AppSync and DynamoDB) and my content storage (S3).

If I want to test only part of my application locally, I can use amplify mock api or amplify mock storage to have only the GraphQL API, or the S3 storage, mocked locally.

Available Now
There are lots of other features that I didn’t have time to cover in this post, the best way to learn is to be curious and get hands on! You can start using Amplify by following the get-started tutorial.

Here you can find a great walkthrough of the features, and a description of how we collaborated with the open source community for this release.

Being able to mock and test your application locally can help you build and refine your ideas faster, let us know what you think in the Amplify CLI GitHub repository.

Danilo

Danilo Poccia

Danilo Poccia

Danilo works with startups and companies of any size to support their innovation. In his role as Evangelist at Amazon Web Services, he leverages his experience to help people bring their ideas to life, focusing on serverless architectures and event-driven programming, and on the technical and business impact of machine learning and edge computing. He is the author of AWS Lambda in Action from Manning.