stubby4j mock(stub)サーバでAPIまわりの開発をスムーズに!
こんにちは@s_tsukaです。
今回はmock(stub)サーバであるstubby4jを紹介します。
みなさんはHTTP GETやHTTP POSTのmockを用意するときは何を使っていますか?自分は特にこれといって決まりは無いのですが、stubby4jというmockサーバがなかなか使いやすかったので、今回はこれについて書いてみます。
mockサーバって何のこと
ここで言うmock(stub)サーバとは特定のHTTP Requestに対して特定のHTTP Responseを返す、開発を便利にするためのサーバのことです。なんのこっちゃという人も居るかと思いますので、以下のようなシーンを挙げます。
- サーバ側はJSONを返して、クライアント側(JS側)はJSONを使って処理を行う
- 外部のサーバにHTTP Requestを投げまくる処理を含む自分のプログラムのテストをしたい。例えば負荷テスト
開発をしていて、このようなシーンに直面したとき、mockサーバを使うという選択肢があります。
mockサーバは特定のHTTP Requestに対して特定のHTTP Responseを返すものです。これをもし自分の開発環境に構築できたら
- JSONを返せるので、クライアント側(JS側)はサーバ側の完成を待たずに開発ができる
- 外部のサーバに実際にリクエストを送らずに済むので、安定してテストができる。外部サーバの所有者に迷惑をかけなくて済む。
というようなメリットを享受できます。
stubbyとstubby4j
stubbyは上記で挙げたようなことを可能にするmockサーバアプリです。
公式では「a small web server for stubbing external systems during development」と言っているので、「開発中、外部システムにスタッビングするための小さなwebサーバ」という感じでしょうか。
nodejs, java, .netの3つの実装があります。中身的には同じはずなので、お好きな環境を使えば良いと思います。
Java版はstubby4j、node版はstubby4node、stubby4netです。動かし方はどれも簡単です。自分は上記の中では最もJavaが好きですし、利用頻度も高いので、Java版であるstubby4jを選択しました。
https://github.com/azagniotov/stubby4j
とりあえず動かす!
非常に簡単に動かすことができます・・・!
stubby4jはRunnable Jar(Fat Jar)としてビルドされてMaven centralで公開されています。
なので、まずはJarをDLします。適当に最新verのjarのリンクからDLしてください。
次にどのような挙動をするかを定義するデータファイルを用意します。ここではとりあえずroutes.ymlという名前で以下のように作成します。
- request:
url: ^/$
method: GET
response:
status: 200
headers:
content-type: text/html
server: stubbedServer/4.2
body: >
<html>
<body>
<p>Hello stubby world!</p>
</body>
</html>
最後に以下のコマンドで実行すれば完了です。
java -jar stubby4j-3.1.3.jar -d routes.yml # (versionは適宜変えてね)
実行すると以下のように出力されるかと思います。
Loaded: [GET] ^/$
Admin portal configured at http://localhost:8889
Admin portal status enabled at http://localhost:8889/status
Stubs portal configured at http://localhost:8882
Stubs portal configured with TLS at https://localhost:7443 using internal keystore
Jetty successfully started
Quit: ctrl-c
いくつかURLが表示されていますが、port 8889の方は一旦無視して、http://localhost:8882にアクセスしてみましょう!
先ほどroutes.ymlで定義したHello stubby world!が表示されると思います。
このように非常に簡単に動かすことが出来ました。
jsonを返すエンドポイントを用意して開発に使う
もうお分かりかと思いますが、上記で作成したデータファイル、つまりroutes.ymlが設定の全て!と言っても過言ではありません。
次はこれを変えてjsonを返すAPIのstubbyingをしてみましょう!
やり方は非常に簡単です。routes.ymlを以下のように変えてみましょう。
- request:
url: ^/$
method: GET
response:
status: 200
headers:
content-type: application/json
server: stubbedServer/4.2
body: >
{
"msg":"Hello!"
"name":"tsukaby"
"age":17
}
これで再度実行すれば正しくapplication/jsonとしてbodyのjsonが返ってきます。
1個しか定義できないの?と思った方、大丈夫です。req/resは配列なので、複数列挙すればOKです。
その他細かい設定
大体使い方が分かってきたところで、細かい設定やオプションの話に移りましょう。ここを読んでおけばstubby4jを使いこなせると思います。
(ぶっちゃけると公式を読んだ方が早いかもしれませんが)
-dで指定するデータファイルの定義
まずデータファイルであるroutes.ymlですが、urlは正規表現です。なので^/$とした場合は先頭も末尾も/で終わるパスになります。^/api/users$と書けば/api/usersだけでしかアクセスできなくなりますし、^/api/usersとして$を抜けばusersの後ろにクエリが 付いていてもアクセス可能になります。
methodは配列で指定できます。なので[GET, POST]とすればGETでもPOSTでも正しくstubbingできるようになります。POSTなどのメソッドに対応できるのは大きいです。GETであればnginxなどでも同じことができますが、完全にPOSTに対応しようとするとnginxでは微妙に困ります(response codeなどの問題で)
headerは見ての通りですね。content-typeとかお好きに設定すれば良いかと思います。
responseですが、勿論任意のステータスコードを返すことが出来ます。
上記の例ではresponseのbody部分に直接レスポンスを書きましたが、bodyではなく、fileと書いて、ファイルパスを指定すれば、そのファイルを返すことが出来ます。htmlなり、jsonなり長くなりそうですし、基本的にはfileを使った方が良さそうですね。以下は例です。
response:
- status: 200
headers:
content-type: application/json
file: ../json/reports.json
latencyでは応答にディレイを持たせられます。無くてもまあ良いですが、適当に指定しておけば実際の環境のレスポンスタイムを模倣できます。ただし、stubby4jはstubbingしているとは言え、超高速でresponse出来る訳ではないので(そんな夢の技術は無い)、latencyを指定しなくてもresponseに5ms〜50msは要すると思っておいた方が良いです。
5〜50は自分が実際に負荷かけて出した大体の数値です。勿論マシンや回線にも左右されます。
javaコマンド実行時のオプション
公式ではこのようになっています。
https://github.com/azagniotov/stubby4j#command-line-switches
usage: java -jar stubby4j-x.x.xx.jar [-a <arg>] [-d <arg>] [-da] [-ds] [-h] [-k <arg>] [-l <arg>] [-m] [-o] [-p <arg>] [-s <arg>] [-t <arg>] [-v] [-w] -a,--admin <arg> Port for admin portal. Defaults to 8889. -d,--data <arg> Data file to pre-load endpoints. Valid YAML 1.1 expected. -da,--disable_admin_portal Does not start Admin portal -ds,--disable_ssl Does not enable SSL connections -h,--help This help text. -k,--keystore <arg> Keystore file for custom TLS. By default TLS is enabled using internal keystore. -l,--location <arg> Hostname at which to bind stubby. -m,--mute Mute console output. -o,--debug Dumps raw HTTP request to the console (if console is not muted!). -p,--password <arg> Password for the provided keystore file. -s,--stubs <arg> Port for stub portal. Defaults to 8882. -t,--tls <arg> Port for TLS connection. Defaults to 7443. -v,--version Prints out to console stubby version. -w,--watch Periodically scans for changes in last modification date of the main YAML and referenced external files (if any). The flag can accept an optional arg value which is the watch scan time in milliseconds. If milliseconds is not provided, the watch scans every 100ms. If last modification date changed since the last scan period, the stub configuration is reloaded
色々ありますが、以下は特に重要です。
- —stubs デフォルトでは8882でlistenしますが、実際にはport 80とかで動かしたいと思いますので、大抵指定することになるでしょう
- —data 上記で何度も言っているデータファイルですね。上記の例ではroutes.ymlという名前で作っています。当然必須です。
- —location これは罠だなーと思いました・・・。デフォルトでhttp://localhost:8882でアクセスできますが、実はlocalhostからの接続しか待ち受けていません。なので、—locationで0.0.0.0を指定して全てのIPからの接続を待ち受ける必要があります。指定しておかないとstubbyをどこかの環境に置いて、いざ外部から接続して使おう!というときに困ります。
まとめ
- mockサーバアプリであるstubby、その中でもJava実装であるstubby4jについて紹介しました。
- stubbyの主要なオプションやymlの書き方について説明しました
mockサーバアプリは他にもいろいろありますが、stubbyはかなり扱いやすく簡単に学習できる方だと思います。ただ、完璧に高負荷を裁ける訳ではないので、負荷試験の外部接続先mockとして使うときは多少エラーが出ることは覚悟しておきましょう。
みなさんもstubbyを使って素敵なmock(stub)ライフを送ってみてはいかがでしょうか?