Androidアプリ開発でREST APIのモックサーバーを用意する方法

こんにちは、ohioshirt - Qiita です。
今回は、業務効率化ツールの話です。

モバイルアプリの開発中に 色々なレスポンスを返して欲しくなることがあります。
例えば、課金ユーザーとそうでないユーザーで レスポンスの形式を変えたいとか、
所属しているグループの状態によってレスポンスの形式を変えたいとか。
もちろん、サーバー/DB側で それぞれの状況に応じたアカウントを作っておくのが一番ですが、
それなりに手間がかかるので、 ダミーのAPIサーバーからレスポンスを返すようにして
済ませることがあります。
これまで扱ってきた方法の変遷を振り返ってみます。
いずれも新しいものではないので紹介は軽めにします。

その1:RetrofitMock

Retrofitは、Androidアプリでよく使われるHTTPクライアントです。
RetrofitMockは、そのRetrofitのモック機能です。
しかし、手軽さに劣るせいか最近はほとんど使わなくなりました。
現在の出番はテストコードを書くときくらいでしょうか。

その2:Prism

Prismは、OpenAPIのモックサーバーです。
OpenAPIは、APIの仕様を記述するためのフォーマットです。
OpenAPIのフォーマットでAPIの仕様を記述すると、
Prismがそれに従ってレスポンスを返してくれます。

弊社はOpenAPI仕様に基づきドキュメントを作成しているので、
そのopenapi.yamlを使って起動するだけ準備完了です。
任意の値が必要になれば、openapi.yamlを修正して
exampleの値を変更します。ほとんどの場合はこれで事足ります。
JSONファイルを指定してもいいです。
日々ドキュメントをメンテナンスされているからこそできることですね。

Prismは、開発PCで動作させることがほとんどであるため、APIサーバーとは別のリクエスト先になります。
この辺の設定をアプリ内でどう定義するかはチーム次第ですが、
開発用のビルドはAPIのURLを動的に変更できるようにして、
そこにモックサーバーを動作させているURLを設定できるようにすると便利だと思います。

その3:Ktor Server

Ktorは、Kotlinで書かれたWebアプリケーションフレームワークです。
Androidアプリ上でも動かすことができるので、
開発用のスマートフォン一台で完結します。 https://ktor.io/docs/create-server.html

サーバーアプリの作成

せっかくなので現在の作り方をなぞってみます。
まずは、Androidプリプロジェクトを作成します。
Ktorを使うために、dependenciesに以下を追加します。
(最近使うようになったVersion Catalog形式で)

[versions]
ktor = "2.3.7"

[libraries]
ktor-server-core = { group = "io.ktor", name = "ktor-server-core", version.ref = "ktor" }
ktor-server-netty-jvm = { group = "io.ktor", name = "ktor-server-netty-jvm", version.ref = "ktor" }

次に、アプリ上でKtorのサーバーを起動します。 高い品質を求められない状況であれば、シンプルに以下のように書けばOKです。 楽に書きたいので、KotlinのCoroutineを使います。

// MainActivity.kt
override fun onCreate(savedInstaneState: Bundle?) {
    // ...
    lifecyclescope.launch {
        embeddedServer(Netty, port = 8080) {
            routing {
                get("/") {
                    call.respondText("Hello, world!")
                }
            }
        }.start(wait = true)
    }
}

これで、http://localhost:8080/ にアクセスすると
Hello, world! と表示されます。
実際に投入するには、以下のようにもう少し複雑なルーティングの定義や制御が必要があるでしょう。

  • APIドキュメントからエンドポイントを抽出してルーティングを定義する
  • APIドキュメントに書かれているサンプルのレスポンスのJSONをアプリ内のassetsに保存しておき、 リクエストに応じて読み込んで返す
  • より柔軟にレスポンスを返すために、 リクエストパラメーターに応じてレスポンスを生成する
  • 全体で一貫性をもたせるために、DBを使ってレスポンスを生成する
  • サーバーアプリ自身で値を変更できるようにする

後半はやりすぎかもしれません。もはやローカルでWebアプリのコンテナを動かす方がいいとすら思えます。
ただ、データの定義はquicktypeを使うことで
JSONからデータクラスを生成でき、
固定のデータを返すだけだった動作から拡張性が向上します。

業務を快適にするためのツールを作るのは楽しいです。
もちろん、それが目的になっては意味がありません。
まだまだ改善の余地はありますが、
今後も時間を作って時間を作るための取り組みをしていきたいと思います。

次に何が欲しいかというと、Bluetoothの通信をエミュレートするツールです。
AkerunアプリはBluetooth通信を使ってAkerunを操作します。
その通信をエミュレートするツールがあれば、
より細かい制御ができるようになり、開発の効率や品質を上げられるでしょう。
先日の記事にもあるように、 通信相手の挙動を制御したい需要は各所にあるのだなと感じます。

これからも、業務を快適にするための活動を続けていきたいと思います。


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp

Akerunにご興味のある方はこちらから akerun.com