开始使用AWS Amplify Mocking来大幅提高GraphQL API开发速度

简要说明

AWS Amplify Advent Calendar 2019、19日目では、AWS Amplify的新功能Mocking如何大幅提高GraphQL API开发速度的方法将会被介绍。

“Amplify Mocking” 是什么意思?

这是2019年8月7日发布的Amplify CLI的新功能(尽管已经过了一段时间)。由于$ amplify push需要引用和更改AWS CloudFormation堆栈,因此这可能需要一些时间。使用$ amplify mock命令,您可以在将更改应用于云资源之前,在本地环境中进行更改后的操作验证。

目前提供的Mocking类别有以下三种。

api(GraphQL): AWS AppSync + Amazon DynamoDB

storage(Content): S3

function: AWS Lambda

本文将详细探讨API(GraphQL)的模拟而将存储和功能的模拟仅作为参考资料分享。

放大模拟指令

$ amplify mock
$ amplify mock api
$ amplify mock storage
$ amplify mock function <functionname>

通过继续指定要Mock的Category来实现Mock,这可以在amplify mock之后进行。由于可以在一个应用程序中创建多个function,因此可以明确传递要Mock的function。如果在不指定Category的情况下执行amplify mock,则会开始Mock api和storage。

希望吸引的读者

给那些正在使用amplify添加api和调整AWS AppSync的人提供一种选择,每次等待amplify push的时间真的很烦人啊。虽然中途会出现React,但不需要任何了解React的知识。

请确认动作环境

    • react 16.12.0

 

    @aws-amplify/cli 4.5.0

可以用以下資料作為參考。

我会附上一些参考资料供您参考。如果只是尝试Mocking功能,最快的方法是参考底部的官方文档。

    • Mocking and Testing Serverless APIs with AWS Amplify – AWS Online Tech Talks – YouTube

 

    • New – Local Mocking and Testing with the Amplify CLI | AWS News Blog

 

    • Developing and testing GraphQL APIs, Storage and Functions with Amplify Framework Local Mocking features | AWS Mobile Blog

 

    • https://aws-amplify.github.io/docs/cli-toolchain/quickstart?sdk=js#mocking-and-testing

 

    https://aws-amplify.github.io/docs/cli-toolchain/usage?sdk=js#mocking-and-testing

准备验证应用程序

反应应用

在这个步骤中,我们将使用React进行操作,但是您也可以使用其他框架(如Vue、Angular、Ionic)来创建应用程序,并且不需要更改任何代码,这也是可以的。

$ npx create-react-app amplify-react
$ cd amplify-react
$ npm start

浏览器启动后,熟悉的起始页面会出现。

image.png

放大器的初始设置

请使用amplify init进行Amplify的初始配置。
假设已经执行过amplify configure。(如果还没有执行amplify configure,请点击此处)
请在${profile name}中输入您正在使用的Amplify AWS Profile的名称。

$ amplify init

? Enter a name for the project amplify-react
? Enter a name for the environment mocktest
? Choose your default editor: Vim (via Terminal, Mac OS only)
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path:  src
? Distribution Directory Path: build
? Build Command:  npm run-script build
? Start Command: npm run-script start
Using default provider  awscloudformation

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html

? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use ${profile name}

创建 GraphQL API

让我们在amplify add api命令中设置用于验证模拟的后端。重点是设置使用API密钥进行一次性设置,并在此基础上添加Amazon Cognito用户池和AWS IAM的额外认证。这是为了在后续使用@auth时进行模拟验证。请参考图片进行设置。

image.png

准备好了!让我们实际使用Mocking。

API 模拟

让我们试试API模拟!

让我们编辑刚刚添加API的AppSync的schema.graphql。

type Todo 
@model 
@key(fields: ["id"])
@auth(rules: [
  {allow: owner, provider: userPools, operations: [create, read, update, delete]},
  {allow: private, provider: userPools, operations: [read]},
  {allow: public, provider: apiKey,operations: [read]},
])
{
  id: ID!
  name: String!
  owner: String!
  description: String
  updatedAt: AWSDatetime
  createdAt: AWSDatetime
}

请参阅我的著作《Amplify CLI GraphQL Transform与AppSync+DynamoDB的指令探究》中对@auth的解释,该指令通过使用@model和@key在schema.graphql中实现以下授权。

    • Cognito User Poolで認証したユーザーに次のアクションを許可

Todoのcreate
自身が作成したアイテムのread, update, delete
他の人が作成したアイテムのread

AppSyncのAPI_KEYで認証したユーザーにはreadのみを許可

在执行”amplify push”之前,让我们先在云资源中模拟一下”amplify mock api”。

$ amplify mock api
Failed to start API Mock endpoint Error: Type "AWSDatetime" not found in document.

我遇到了一个错误,显示为找不到AWSDatetime类型。根据AppSync的标量类型,应该使用AWSDateTime才正确。我犯了个错误,让我们编辑schema.graphql解决吧。

type Todo 
@model 
@key(fields: ["id"])
@auth(rules: [
  {allow: owner, provider: userPools, operations: [create, read, update, delete]},
  {allow: private, provider: userPools, operations: [read]},
  {allow: public, provider: iam, operations: [read]},
  {allow: public, provider: apiKey,operations: [read]},
])
{
  id: ID!
  name: String!
  owner: String!
  description: String
  updatedAt: AWSDateTime
  createdAt: AWSDateTime
}

如果您正在运行 magnify mock api,则它将检测到更改并重新加载。

image.png

这次编译通过了!可以在不进行$ amplify push的情况下试用这些细小错误真是令人高兴。
为了自动生成用于从前端使用GraphQL进行查询的代码,我们会问你一些问题。你可以选择默认选项。

在正常情况下,会显示用于Mock的API端点。但如果在出现错误后进行上述设置,则似乎无法显示API端点。请先使用Ctrl+C停止执行,然后再次执行$ amplify mock api。

image.png

http://192.168.1.6:20002上已经启动了GraphQL的模拟服务器!其中的192.168.1.6部分是您在验证环境网络中分配给您的个人电脑(或服务器等)的本地IP地址。

通过API模拟创建的东西

当能够运行API模拟时,请确保通过`amplify mock api`命令确认所创建的内容,并对整体情况有所了解。根据《AWS新闻博客》中的“使用Amplify CLI进行本地模拟和测试”的文章,`amplify mock api`命令将创建以下资源。

您的API所需的GraphQL转换
使用DynamoDB本地版本来本地化管理API数据
基于开源OneGraph graphiql-explorer插件的Amplify GraphQL Explorer

    • GraphQL transformatinos

schema.graphqlからGraphQLで使用されるより詳細なschema、resolver、およびフロントエンドで使用するコードを生成

DynamoDB Local

SQLiteのDBをDynamoDB風のインタフェースでラップしたもので、Amplify GraphQL ExplorerのDBとして使用
SQLiteなのでSQLiteが読めるプラグインをいれて自由に閲覧・編集可能

Amplify GraphQL Explorer

OSSのOneGraph graphiql-explorer pluginをベースに開発されたGraphiQL(GraphQL IDEとも)プラグイン
HTTPによるクエリを受け付けるGraphQLエンドポイントと、クエリを手軽に試せるGUIを提供

没有被介绍,但是一种相对便利的方法是使用aws-exports在模拟期间将本地的Mock API Endpoint指定为目标。稍后我们会确认这个功能。

GraphQL 探索器放大

image.png

请打开 Amplify GraphQL Explorer。我们来创建一些项目。

image.png
    1. 点击”ADD NEW MUTATION”

 

    1. 点击”createTodo”

 

    1. 在紫色文字的input字段中,填写必填字段id、name、owner(必填字段将带有*,如id*)

 

    勾选要返回的字段(本例中全选)

有了GraphiQL的支持,我们可以非常轻松地编写mutation。现在,点击上方的▶来执行它。

image.png

实际结果将显示在右侧。出现错误。当阅读消息时,显示了没有访问createTodo权限的信息。让我们回想一下在schema.graphql中写的内容。

允许Cognito用户池中经过身份验证的用户执行以下操作:
– 创建待办事项
– 读取、更新、删除自己创建的项目
– 读取其他人创建的项目

对于经过IAM身份验证的用户和使用AppSync的API_KEY身份验证的用户,只允许读取操作。

当查看右上角时,会显示“Use: API Key”。从Amplify GraphQL Explorer发出查询时,可以明确使用API_KEY作为身份验证信息。由于使用API_KEY进行身份验证的用户仅获得读取权限,因此被拒绝访问。这表明Amplify GraphQL Explorer有效地再现了@auth进行授权的功能。

那么,让我们切换到具有create权限的Cognito用户池认证的用户。
点击API密钥,并切换到用户池。

image.png

接下来点击旁边的“更新身份验证”按钮,打开“身份验证选项”。
在“用户名”和“电子邮件”字段中输入适当的值,然后点击“生成令牌”。
请注意,用户名需要与变异中的input的owner字段匹配。

image.png

让我们尝试在这种状态下再次执行变异。

image.png

我成功地进行了无事变异!

image.png
image.png

我们失败了,就像设定的一样。
最后,我们将API_KEY身份验证改为listTodo。

image.png

已经确认可以通过 API_KEY 认证进行读取。

从本地的React应用程序调用模拟的端点

当你在Amplify CLI中使用`amplify add {category}`并执行`amplify push`时,它会自动将Amplify Framework(SDK)创建的资源所需的信息写入到aws-exports.js文件中。通过使用aws-exports.js文件,你可以轻松地进行Amplify的初始设定,并且即使进行资源的修改或添加,也无需修改配置,非常方便。

例如,在JavaScript中,可以像下面这样进行Amplify的设置。

import awsmobile from './aws-exports';
import Amplify from 'aws-amplify';

Amplify.configure(awsmobile)

让我们查看aws-exports.js文件的内容。

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-west-2"
};

export default awsmobile;

这一次因为从未执行过$ amplify push,所以没有任何关于资源的描述。在这种状态下,如果执行$ amplify mock api会怎么样呢?

$ amplify mock api

让我们保持API Mocking的状态,并查看aws-exports.js文件。

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-west-2",
    "aws_appsync_graphqlEndpoint": "http://10.221.93.66:20002/graphql",
    "aws_appsync_region": "us-west-2",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "da2-fakeApiId123456",
    "aws_appsync_dangerously_connect_to_http_endpoint_for_testing": true
};

export default awsmobile;

只需要一种选择:
在进行API Mocking时,它会修改aws-exports.js以指向本地的GraphQL端点!很方便!顺便提一句,这里使用了API_KEY认证,但在前面的Amplify GraphQL Explorer中进行Update Auth并设置为Use: User Pool后,似乎不会在aws-exports.js中反映出来…让我们期待更新吧。

现在,让我们使用Ctrl+C退出API Mocking,然后检查aws-exports.js文件。

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-west-2"
};


export default awsmobile;

你可以看到它已经回到了空荡荡的状态。

API伪造技巧的建议

我将为您介绍一些关于API Mocking的小知识。

支持API Mocking的指令

根据 https://aws-amplify.github.io/docs/cli-toolchain/usage?sdk=js#api-mocking-setup,目前仅有5个指令与$ amplify mock api功能相匹配。仅@searchable和@prediction指令不与之匹配。

- @auth
- @key
- @connection
- @versioned
- @function

对DynamoDB Local进行破坏性的更改

请注意:下面介绍的技巧是一些秘籍,可能在未来的更新中变得不再需要,或者本来就有其他方法。(如果有其他方法,请务必告诉我们!)请您通过查看文档或GitHub获取最新信息。

在进行开发时,有时可能会希望对DynamoDB进行破坏性的更改,涉及到PK和SK的变更。如果是在生产环境中,可能需要添加GSI(全局二级索引)或者在维护窗口中进行表迁移。不好意思再次提及,如果您感兴趣,我在之前的Amplify Advent Calendar文章中介绍了如何使用Amplify的GSI功能,请随便参阅。

我突然有一股冲动,想要在name字段而不是id字段上进行查询。让我们将schema.graphql更改为以下方式。

type Todo 
@model 
@key(fields: ["name"])
@auth(rules: [
  {allow: owner, provider: userPools, operations: [create, read, update, delete]},
  {allow: private, provider: userPools, operations: [read]},
  {allow: public, provider: iam, operations: [read]},
  {allow: public, provider: apiKey,operations: [read]},
])
{
  id: ID!
  name: String!
  owner: String!
  description: String
  updatedAt: AWSDateTime
  createdAt: AWSDateTime
}

当查看amplify mock api的日志时,似乎可以很顺利地进行更改。

GraphQL schema compiled successfully.

...(中略)...

Creating table DataStore locally
Creating table TodoTable locally
Running GraphQL codegen
✔ Generated GraphQL operations successfully and saved at src/graphql

请确保GraphQL Explorer已重新加载,然后尝试执行Mutation。
请确认为Use User Pool方法。

image.png

DynamoDB: 发生了ValidationException。这是因为Validator将PK, SK转换后的Mutation投入了与创建时相同的DynamoDB Local中。(顺便提一下,对于$ amplify push来说,包含DynamoDB的PK, SK更新的更改会在CloudFormation执行时被拒绝。)
在这种情况下,如果是云资源,可以先将想要修改的type完全注释掉,然后执行$ amplify push删除DynamoDB Table,然后再取消注释并执行$ amplify push重新创建。对于API Mocking的情况,删除SQLite文件可能会有帮助。

$ rm amplify/mock-data/dynamodb/fake_us-fake-1.db
$ amplify mock api
GraphQL schema compiled successfully.

Creating table DataStore locally
Creating table TodoTable locally
Running GraphQL codegen
✔ Generated GraphQL operations successfully and saved at src/graphql
AppSync Mock endpoint is running at http://10.221.93.17:20002

从日志中可以看出TodoTable已被创建。更新Amplify GraphQL Explorer,然后再次执行Mutation尝试。

image.png

接下来执行查询。

image.png

没有问题,我能够使用新的PK字段name来调用getTodo。

总结

    • Mockingにより、クラウドリソースに変更反映する前に、変更後の動作確認をローカル環境で行うことが可能になります

 

    • Mockingが提供されているCategoryはAPI(GraphQL)、Storage、Functionの三つ

 

    • API Mockingが提供するのは次の四つです

GraphQL transformations
DynamoDB Local
Amplify GraphQL Explorer
aws-exports.jsの自動編集

通过 Amplify Mocking,我们感受到开发速度大幅提高。不太可能回到那个为了详细更改确认而进行 amplify push 的时代了。请务必尝试 API Mocking,还有 Storage、Function 的 Mocking!

AWS Amplify Advent Calendar,明天是 @rtaguchi 先生的轮到!

bannerAds