Help us understand the problem. What is going on with this article?

GraphQL API開発スピードを爆上げするAWS Amplify Mockingことはじめ

概要

AWS Amplify Advent Calendar 2019、19日目はAWS Amplifyの新機能MockingでGraphQL API開発スピードを爆上げする方法について書いていきます!

Amplify Mockingとは

2019.08.07に発表されたAmplify CLIの新(というにはいささか時間が経ってしまった)機能です。$ amplify pushはAWS CloudFormationのスタックの参照と変更を行うため、それなりに時間がかかってしまいます。$ amplify mockコマンドを使用すると、$ amplify pushでクラウドリソースに変更反映する前に、変更後の動作確認をローカル環境で行うことが可能です。

現在Mockingが提供されているCategoryは、以下の3つです。

  • api(GraphQL): AWS AppSync + Amazon DynamoDB
  • storage(Content): S3
  • function: AWS Lambda

storagefunctionのMockingについては参考資料の共有に留め、本記事ではAPI(GraphQL)のMockingについて詳しく見ていきます。

Amplify Mock Commands

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

amplify mockに続いてMockしたいCategoryを続けることでMockすることができます。functionは一つのアプリケーションに複数のfunctionを作成することができるため、Mockしたいfunctionを明示的に渡します。Categoryを指定せずamplify mockを実行した場合は、apistorageのMockが始まります。

想定読者

$ amplify add apiしてAWS AppSyncいじってるけど、毎回amplify pushの時間待つのだるいなぁ、とお考えの悩めるあなたに捧げます。途中Reactが出てきますが、一切触らないのでReactの知識は必要ありません。

動作確認環境

  • react 16.12.0
  • @aws-amplify/cli 4.5.0

参考資料

いくつか参考にした資料を載せておきます。Mockingを試すだけであれば、一番下の公式ドキュメントが早いです。

検証用アプリケーションの準備

React App

本手順ではReactで進めますが、一切コードをいじらないので他のフレームワーク(Vue, Angular,Ionic)でアプリを作っていただいても大丈夫です。

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

ブラウザが立ち上がり、おなじみのスタートページが現れます。

image.png

Amplifyの初期設定

amplify initでAmplifyの初期設定を行います。
amplify configureは一度実行している想定です。(amplify configureがまだの方はコチラ)
${profile name}にはご自身が使用されているAmplify用のAWS Profile名を入力してください。

console
$ 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でMockingの検証に使用するBackendを設定していきましょう。
ポイントとしては一度API KEYでセットアップした上で、追加でAmazon Cognito User PoolとAWS IAMを利用した認証を追加しています。これは後ほど@authを利用した際のMockingを行うためです。画像を参考に設定してみてください。

image.png

準備完了です!Mockingを実際に使ってみましょう。

API Mocking

API Mockingを試してみよう!

先ほどadd apiしたAppSyncのschema.graphqlを編集しましょう。

amplify/backend/api/amplifymocking/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
}

@authについての解説は拙著Amplify CLI GraphQL TransformとディレクティブでAppSync+DynamoDBをいじってみよう!(@model @auth, @key) - Qiitaをご覧ください。上記のschema.graphqlにおける@authは、以下の認可を実現します。

  • Cognito User Poolで認証したユーザーに次のアクションを許可
    • Todoのcreate
    • 自身が作成したアイテムのread, update, delete
    • 他の人が作成したアイテムのread
  • AppSyncのAPI_KEYで認証したユーザーにはreadのみを許可

ではこの設定をクラウドのリソースに反映する$ amplify push...の前に!$ amplify mock apiしてみましょう。

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

AWSDatetime型なんて見つからないよ、というエラーが表示されました。AppSyncのスカラー型によれば、正しくはAWSDateTimeです。うっかり間違えてしまいました。schema.graphqlを編集しましょう。

amplify/backend/api/amplifymocking/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
}

$ amplify mock apiを実行したままであれば、変更を検知して再読み込みしてくれます。

image.png

今回はコンパイルが通りました!こうした細かな間違いを$ amplify pushをせずに試せるのは嬉しいですね。
フロントエンドからGraphQLでクエリするためのコードを自動生成するため、いくつか聞かれます。全てデフォルトの選択肢で大丈夫です。

本来であればMock用のAPIエンドポイントが表示されるのですが、Error後に上記の設定を行うとAPIエンドポイントが表示されないようです。一度Ctrl+Cで実行を止め、再度$ amplify mock apiしましょう。

image.png

http://192.168.1.6:20002でGraphQLのMockサーバーが立ち上がりました!
192.168.1.6の部分は検証環境のネットワークでご自身のPC(またはサーバーなど)に割り当てられたローカルIPアドレスになります。

API Mockingで作成されるもの

API Mockingが動かせたところで、$ amplify mock apiした時に何が作られているのか確認して、全体感を抑えておきましょう。
New – Local Mocking and Testing with the Amplify CLI | AWS News Blogによれば、$ amplify mock apiによって以下のリソースが作成されます。

  • the GraphQL transformations required by your API
  • DynamoDB Local to manage your API data locally
  • the Amplify GraphQL Explorer, based on the open source OneGraph graphiql-explorer plugin
  • 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をMockingの間だけlocalのMock API Endpointを指すように変更してくれる機能です。これについても後ほど確認します。

Amplify GraphQL Explorer

前項で立ち上がったエンドポイントにアクセスしてみましょう。
http://192.168.1.6:20002
image.png

Amplify GraphQL Explorerが立ち上がっています。いくつかアイテムを作成しましょう。

image.png

  1. + ADD NEW MUTATIONをクリック
  2. createTodoをクリック
  3. 紫文字のinputフィールドのうち、必須であるid, name, ownerを適当に埋めましょう(必須フィールドにはid*のように*がついています)
  4. 返り値として欲しいフィールドにチェックを入れます(今回は全て)

このように、GraphiQLのサポートのもと、非常に簡単にmutationを書くことができました。それでは実際に上部の▶ をクリックして実行してみましょう。

image.png

右側に実行結果が表示されます。エラーがでました。メッセージを読むとcreateTodoにアクセスする権限がありませんと表示されます。
schema.graphqlで書いた内容を思い出してみましょう。

  • Cognito User Poolで認証したユーザーに次のアクションを許可
    • Todoのcreate
    • 自身が作成したアイテムのread, update, delete
    • 他の人が作成したアイテムのread
  • IAMで認証したユーザーと、AppSyncのAPI_KEYで認証したユーザーにはreadのみを許可

右上を見ると、Use: API Keyと表示されており、Amplify GraphQL Explorerがクエリを発行する際、認証情報としてAPI_KEYを使っていることがわかります。API_KEYで認証したユーザーにはread権限しか与えていないため弾かれたのですね。Amplify GraphQL Explorerがちゃんと@authを再現して認可をしていることがわかります。

では、create権限をもったCognito User Poolで認証したユーザーに切り替えてみましょう。
Use: API Keyをクリックし、Use: User Poolに切り替えます。

image.png

続いて隣のUpdate Authをクリックし、Auth Optionsを開きましょう。
UsernameとEmailに適当な値を入力し、Generate Tokenをクリックします。
UsernameはMutationのinputのownerと一致する必要があることに注意してください。

image.png

この状態で再度Mutationを実行してみましょう。

image.png

無事Mutationすることができました!

続けて別のユーザーに切り替えてみます。再度Update Authをクリックしてユーザーの情報を書き換えましょう。
image.png
Generate Token後、先ほど他のユーザー作ったTodoにMutation(update)をしてみます。

image.png

失敗しますね、設定通りです。
最後にAPI_KEY認証に変え、listTodoしてみましょう。

image.png

API_KEY認証でreadできることが確認できました。

ローカルのReactアプリからMockされたEndpointを叩く

Amplify CLIでは、 $ amplify add {category}して$ amplify pushすると、Amplify Framework(SDK)から作成したリソースを叩くために必要な情報をaws-exports.jsに吐き出してくれます。aws-exports.jsの中身を使ってAmplifyの初期設定を行うとリソース変更や追加をしてもコンフィグを書き換える必要がなくなり、非常に楽です。
例えばJavaScriptでは、次のようにAmplifyの設定を行います。

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

Amplify.configure(awsmobile)

aws-exports.jsの中身をみてみましょう。

src/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するとどうなるのでしょうか。

console
$ amplify mock api

でAPI Mockingしたまま、aws-exports.jsを確認してみましょう。

src/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をしている間だけ、ローカルのGraphQL Endpointを指すようにaws-exports.jsを書き換えてくれるのです!便利!
ちなみにここではAPI_KEY認証を使っていますが、前述のAmplify GraphQL ExplorerのUpdate Authを行ってUse: User Poolにしてもaws-exports.jsには反映されないようです。。。updateに期待しましょう。

ではAPI MockingをCtrl+Cで抜けてaws-exports.jsを確認してみます。

src/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 Mocking Tips

API Mockingのちょっとした豆知識を紹介します。

API Mockingに対応しているディレクティブ

https://aws-amplify.github.io/docs/cli-toolchain/usage?sdk=js#api-mocking-setup によれば、$ amplify mock apiに対応しているディレクティブは執筆時点で次の5つです。@searchable@predictionだけ対応していません。

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

DynamoDB Localに破壊的な変更を加える

注)以下で紹介するテクニックは裏技的なもので、今後アップデートにより必要なくなったり、そもそも別の方法があったりするかもしれないものです。(他に方法があればぜひ教えてください!)最新情報はドキュメントやGitHubの確認をお願いします。

開発していると、DynamoDBにPK,SKの変更を伴う破壊的な変更をしたくなる場合があります。本番環境であればGSI(グローバルセカンダリインデックス)の追加や、メンテナンスウィンドウを設けてのTable移行になるかと思います。重ねての紹介で恐縮ですが、AmplifyでGSIを使ってみようという内容も前回のAmplify Advent Calendar記事で書いたのでよければご覧ください。

突如idでなくnameフィールドでクエリしたい衝動に駆られました。schema.graphqlを次のように変更しましょう。

amplify/backend/api/amplifymocking/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のログを見ると、普通に変更できていそうです。

console
GraphQL schema compiled successfully.

...(中略)...

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

Amplify GraphQL Exploererはホットリロードされないので、一度リロードしてからMutationを実行してみましょう。
Use User Poolになっていることを確認してください。

image.png

DynamoDB:ValidationExceptionが発生しました。作成時のPK, SKのままのDynamoDB LocalにPK変換後のMutationを投げてしまったためです。(ちなみに$ amplify pushの場合、DynamoDBのPK,SKの更新を伴う変更は、CloudFormation実行時に弾かれます。)
こうした場合、クラウドリソースであれば一度変更したいtypeをまるっとコメントアウトして$ amplify pushしてDynamoDB Tableを削除し、その後コメントアウトを解除して$ amplify pushすることで再度作成するというテクニックがあります。API Mockingの場合にはSQLiteのファイルを削除するとよさそうです。

console
$ 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

続いてQueryを実行します。

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 さんです!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした