かんたん！Postman gRPC用モックサーバーの設定方法

# はじめに

PostmanはgPRC用の専用クライアントUIがあります。また、通常のREST (HTTP UI)と同じように gRPC用のモックAPIテストのためのモックサーバーの利用ができます。本記事では、テスト用のgRPC APIサーバーを使用して、gRPCリクエスト設定とgRPC用モックサーバーの設定方法を簡単に紹介します。

＊ 記事を通じて、[日本語モード](https://qiita.com/umorih-hm/items/ad742fe62c9acfc99bd0)のUIで解説します。

## Postman gRPC クライアントとは？

PostmanのgRPCクライアントには、gRPCリクエストを呼び出してテストするためのさまざまな専用ツール、ビュー、コントロールが用意されています。

https://learning.postman.com/docs/sending-requests/grpc/grpc-request-interface/

大きく次の4つのことができます: 

- gRPCのサービス定義を管理できる。gRPCではインターフェース定義言語 (IDL)として[protobuf](https://protobuf.dev/)を使用
- gRPCリクエストの送信およびJavaScriptでテストができる
- gRPCサンプルのリクエストとレスポンスのペアを保存できる
- gRPC専用のモックサーバーを活用してモックAPIテストができる

ちなみに、PostmanではJSONインターフェースを使用して gRPCデータを読み書きできることが、大きな特徴です。ProtobufタイプとJSONのマッピングについてはこちらのページが参考になります。

https://learning.postman.com/docs/sending-requests/grpc/understanding-grpc-types/

## Postman gRPCモックサーバーとは？

gRPCモックサーバーは、gRPC APIのエンドポイントへのリクエストのサンプルデータを返し、実際のAPIの動作をシミュレートします。APIが実装される前に、モックサーバーを使用して APIをテストできます。

なお、Postmanには[REST用モックサーバー](https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/mock-an-api/)があります。REST用モックサーバーは、各リクエストにリンクされたサンプルレスポンスを返すことで、APIエンドポイントをシミュレートしますが、このgPRCモックサーバーは、このREST用モックサーバーとは独立した機能であり、実装も異なります。ご注意ください。

gRPCモックサーバーの詳細についてはこちらのページが参考になります。

https://learning.postman.com/docs/sending-requests/grpc/using-grpc-mock/

# gRPC APIサーバーの準備

テスト用のAPIサーバーを準備します。このAPIサーバーは、データストアにmongoDBを活用してgRPCでやりとりをするシンプルなCRUDサービスです。

https://github.com/yokawasa/grpc-bookstore

## サービス定義ファイル

後述のgRPCリクエスト設定で利用するAPIサーバーのサービス定義ファイル (.proto)ファイル([book.proto](https://github.com/yokawasa/grpc-bookstore/blob/main/proto/book.proto))は以下の通りです。

```go
syntax = "proto3";

package book;

option go_package = "github.com/yokawasa/grpc-bookstore";

service Bookstore {
    rpc PostBook(BookRequest) returns (BookResponse);
    rpc GetBook(GetBookReq) returns (BookResponse);
    rpc UpdateBook(BookRequest) returns (BookResponse);
    rpc DeleteBook(GetBookReq) returns (DeleteBookRes);
    rpc GetAllBooks(GetAllReq) returns (GetAllResponse);
}

message Book {
    string bookID= 1;
    string bookName = 2;
    string category = 3;
    string author = 4;
}

message BookRequest {Book book = 1;} 

message BookResponse {Book book = 1;}

message GetBookReq {string id = 1;}

message DeleteBookRes {int64 deleted = 1;}

message GetAllReq {};

message GetAllResponse {repeated Book book = 1;}
```

## APIサーバー クイックスタート

まずは、APIサーバーのコードをダウンロードします。

```bash
git clone https://github.com/yokawasa/grpc-bookstore.git
```

ダウンロードした`grpc-bookstore`ディレクトリに移動して、`docker compose up`コマンドでmongoDBサーバーを起動します

```bash
docker compose up -d

# 出力結果
[+] Running 3/3
 ✔ Network grpc-bookstore_default        Created                                                                  0.0s
 ✔ Container mongo-server                Started                                                                  0.2s
 ✔ Container grpc-bookstore-db-client-1  Started                                                                  0.3s
```

続いて、.envファイルを作成し、次のようにMONGO_IMAGEを定義します。なお、同ディレクトリにある`.env.example` をコピペするでもOKです。

```bash
cat << EOF | tee .env
MONGO_IMAGE="mongodb://mongoadmin:secret@localhost:27017/"
EOF
```

それでは、テスト用のgRPCサーバーを起動します。

```bash
go run main.go
```

これで準備完了です。

ちなみに、全てのテストが終わったら次のようにmongoDBサーバーを停止することをお忘れなく。

```bash
docker compose down
```

# gRPCリクエストの設定

それでは、Postmanアプリで、gRPCリクエストを設定していきます。

## 1. 新規リクエスト作成

Postmanアプリを立ち上げ、作業用のワークスペース（ここでは`My Workspace`）のコレクションメニューをクリックします。そして、次のように`新規`ボタンをクリックして、gRPCを選択して新規リクエストを作成します。

![Screenshot 2024-12-25 at 10.39.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/14086282-c26a-0c29-77c4-0ed8a2de3a88.png)


## 2. サービス定義 (Service Definitions) (`.proto`)のインポート

新しいgRPCリクエスト設定画面にて、次の手順でサービス定義ファイル([book.proto](https://github.com/yokawasa/grpc-bookstore/blob/main/proto/book.proto))をインポートします。

1. `[サービス定義]`タブに移動し、`.proto ファイルのインポート`を選択
2. `.proto`ファイルをローカルシステムからドラッグアンドドロップするか、`Choose a File`を選択してファイルエクスプローラーを開いて指定します
3. ファイルを選択したら、`Import as API` インターフェースが表示されます
4. `Import as API`をクリックして、新しい APIに名前を付け、`Create a New API`ボタンを選択します。ここでは `bookstore API`という名前をつけます

![Screenshot 2024-12-25 at 10.45.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/08a35573-674a-e50f-2614-304aa295ff85.png)

これで、このAPIをリクエスト内でサービス定義として使用できるようになります。以後サービス定義の設定の際は、ここで設定したAPI (`bookstore API`)を選択します。

## 3. gRPCリクエストのサーバーアドレス、メソッド選択、メッセージ入力 

PostBookというサービス呼び出しのためのリクエスト設定を行います。次の内容でリクエストを設定します。


![Screenshot 2024-12-25 at 10.49.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/c8d72cfb-27a5-9281-2533-3215f906da40.png)

- サーバーアドレスURL: `localhost:9090` 
- メソッド選択: ドロップダウンリストからPostBookメソッドを選択
- 送信するメッセージ: 次のJSONをメッセージに設定
    ```json
    {
        "book": {
            "bookID": "12348",
            "bookName": "sample book3",
            "category": "comic",
            "author": "Test Test"
        }
    }
    ```

入力が完了したらリクエストを「保存」ボタンを押して`gRPC - bookstore`という名前のコレクションに保存します。これでPostBookリクエストの設定は完了です。

同じように、GetBookサービスを呼び出すためのGetBookリクエストを設定を行います。次の内容でリクエストを設定します。

- サーバーアドレスURL: `localhost:9090` 
- メソッド選択: ドロップダウンリストからGetBookメソッドを選択
- 送信するメッセージ: 次のJSONをメッセージに設定
    ```json
    {
        "id": "12348"
    }
    ```

入力が完了したら同様にリクエストを「保存」ボタンを押して`gRPC - bookstore`という名前のコレクションに保存します。

## 4. リクエスト実行 / サービス呼び出し(Invoke)

3で設定したPostBookとGetBookリクエストを呼び出し(invoke)していきます。

まずは、PostBookリクエストで`呼び出し(Invoke)`ボタンを押して、PostBookメソッドを呼び出します。実行すると、次のようにレスポンスが画面下半分のレスポンスエリアに出力されます。

![Screenshot 2024-12-25 at 10.56.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/8e14879b-87bf-5a2a-2612-fa16808b3eec.png)

同様に、GetBookリクエストも実行してみてください。PostBookと同じように、レスポンスが画面下半分のレスポンスエリアに出力されます。

RESTのクライアントI/Fとほぼ同じ使用感であることがお分かりいただけるかと思います。

# gRPCモックサーバー設定

それでは、いよいよgRPCモックサーバーを設定していきます。

## gRPCモックサーバー作成

PostBookリクエストを使ってgRPCモックサーバーを設定します。

まずは、PostBookのサービス定義のところが、さきほどAPIとしてインポートした`bookstore API`が選択されていることを確認してください。

![Screenshot 2024-12-25 at 11.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/d2e949d5-fec9-2c9a-62b0-88de3e52deb8.png)

次に、サーバーアドレスURL部分を、実体である`localhost:9090` ではなく、空にします。すると、次のようなドロップダウンが表示されので、そこで`bookstore APIのモックURLを使う`を選択します。 

![Screenshot 2024-12-25 at 11.13.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/e832fba5-5ad4-a0a0-3cf1-6a7f8b61c8d7.png)

これで、MockURL(`<mock-name>.srv.pstmn.io`）自動生成されます。ここではg-25w1wwzn8xm1lr68wr40z60w7gm1xx.srv.pstmn.io（仮）という名前のMockURLが作成されてます。

たったこれだけです。

## モックサーバーにリクエスト送信

モックサーバーにリクエスト送信してみます。下記のようにモックのデータが返却されます。

![Screenshot 2024-12-25 at 11.02.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/cf4c5aa2-4baa-b390-3289-4312dbd8b7cf.png)

連続でリクエストを送信してみてください。モックサーバーにリクエストを送信するたびに、異なるランダム データが返却されることが確認できます。

また、GetBookリクエストでも、モックサーバーにリクエストを送信するたびにランダムなデータが返却されます。

## レスポンスを固定にする方法

上述のように、gRPCモックサーバーでは、モックサーバーにリクエストを送信するたびにランダムなデータが返却されます。ただし、テストを作成している場合は、毎回同じ応答を取得する必要がある場合があるかと思います。ここでは、レスポンスを固定にする方法を紹介します。

レスポンスの固定にはメタデータのseedを利用します。各レスポンスのメタデータには、次のようにseedが含まれてます。

![Screenshot 2024-12-25 at 11.03.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/f91ba3c7-d11e-56a6-11ee-1942ee194f14.png)

このseedは乱数となってますが、リクエストのメタデータ定義で固定のseedを渡すと、毎回同じレスポンスが返されるようになります。

![Screenshot 2024-12-25 at 11.04.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103420/4a9d73f6-bfca-43c4-dae2-5e3d9dec379a.png)

# さいごに

Postmanを使ったgRPCリクエストの設定やモックサーバーの活用方法を紹介しました。gRPCは高性能な通信プロトコルとして注目されていますが、Postmanの直感的なUIを活用することで、比較的敷居低くgRPCでのテストができます。また、gRPCモックサーバーを活用することで、開発中のgRPC APIだったり、継続的な実行シナリオにおいて、柔軟かつ安定的にテストができるようになります。ぜひ皆さんも試してみてください。