0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

sbtでHTTP接続テスト用のMockServerを立てる

0
Last updated at Posted at 2019-08-30

経緯

Scaladia というDIフレームワークを作っています。

この中に、_akka http_を適当にラップしたモジュールがあるんですが、
_HTTPクライアント_を作る上で、そのクライアントを通してちゃんとHTTP通信できるのかをテストしなきゃいけません。

そんなにまだ開発の進んでいないmoduleだったので今までは暫定的によくないこととしりつつ、ネタ要素の強い適当なAPIを使っていました。
もちろん、テスト回した時に数回叩くくらいだったので、迷惑はかからないだろうという前提です。

でもやっぱり外部リソースに依存するテストを書いてしまうとネットワーク環境がないと動かないテストになってしまうので、環境問わず動くテストを用意しようということで、今回は sbt test の際にHTTP系モジュールだけLocalのHTTP Serverにリクエストさせるようにしました。

意外と類似情報がなかったので、HTTP関係のOSSとかどうしてるんだろうなと思いつつ、ひとまず実現できたので記録しようと思います。

test classpath内でHTTPサーバーを立てればいいのでは?

それも考えたのですが、このフレームワークではAkka HTTPを使用しており、HTTPサーバーを起動するに当たって、
application.conf

akka {
  ~~
}

的なのを用意しないとActorSystemのインスタンスを作れなくてエラーになります。
んーテストとはいえ、もうちょっと美しい感じでできないかな・・・と思い、その解法は使いませんでした。
単純に src/test/resources にtest用のconfを置くのはダサい気がしたというだけですね。

そして、ScalaでHTTP Serverを立てる場合、classのライフサイクルを意識して、TEST中に一回だけしか起動しないように注意する必要があるので、ちょっとシンプルさにかけるかなと思いました。

かといって、test時だけFinatraなど他のHTTPサーバーを立てるのなんて論外なので、採用しませんでした。

どうしたか

http関連モジュールのテスト時のみ、npmでlocalにjson-serverを立ち上げました。

npmに、 json-server という、なかなか便利なmoduleがあるんですよね。
json-server --watch [jsonFile] とするだけで、endpointとresponseを作ってくれます。

まずは endpointresponse を json で定義します。

{
  "endpoint": {
    "status": "success",
    "value": {
      "id": 90,
      "joke": "Chuck Norris always knows the EXACT location of Carmen SanDiego.",
      "categories": []
    }
  }
}

これを json-serverに渡すと、 http://localhost:3000/endpoint

{
  "status": "success",
  "value": {
    "id": 90,
    "joke": "Chuck Norris always knows the EXACT location of Carmen SanDiego.",
    "categories": []
  }
}

を返すAPIになります。

続いて、 json-serverを起動するshellです。

  • なかったらnvmをinstall
  • なかったらnpmをinstall
  • なかったらjson-serverをinstall
  • json-serverを起動する
# !/bin/bash

script=$(cd $(dirname $0); pwd)

install_nvm() {
  if ! test -s $HOME/.nvm; then
    echo "NVM installing..."
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
  fi

  export NVM_DIR="$HOME/.nvm"
  [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

  echo "NVM: `nvm --version`"
}

install_npm() {
  npm_exist=`npm --version; echo $?`
  if test $npm_exist -ne 0; then
    echo "NPM installing..."
    nvm install stable
  fi

  echo "NPM: `npm --version`"
}

install_json_server() {
  if test `npm ls -g --depth=0 | grep json-server | wc -l` -eq 0; then
    echo "JSON-SERVER installing"
    npm install -g json-server
  fi
}

run_jsonserver() {
  json-server --watch ${script}/mock-response.json &
  sleep 2
}

install_nvm
install_npm
install_json_server
run_jsonserver

で json-serverを終了するスクリプト

# !/bin/bash

if test `ps -ef | grep "json-server --watch" | wc -l` -ne 0; then
  ps -ef | grep "json-server --watch" | grep -v "grep" | awk '{print $2}' | xargs kill
fi

これで必要なものは揃ったので、test時にこいつらを叩かせます。
今回はOSSの事例の紹介なので、設定まるごと載せてしまいます。

  .settings(
    name := "scaladia-http",
    description := "Http client for Scala.",
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-http" % "10.1.8",
      "com.typesafe.akka" %% "akka-actor" % "2.5.23",
      "com.typesafe.akka" %% "akka-stream" % "2.5.23",
      "com.typesafe.akka" %% "akka-http-jackson" % "10.1.8",
      "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.9.9"
    ),
    unmanagedClasspath in Test ++= (unmanagedResources in Compile).value,
    
    testOptions in Test ++= Seq(
      Tests.Setup { _ =>
        import scala.sys.process._
  
        Process("sh sh/setup-testing-http-server.sh").run
      },
      Tests.Cleanup { _ =>
        import scala.sys.process._

        Process("sh sh/shutdown-testing-http-server.sh").run
      }
    )
  )

Tests.Setup でテスト前にserverを起動
Tests.Cleanup で終了時にserverをkill

という感じです。

どっちが美しいかと言われると、人の好み感が強いですが、
個人的に、classのライフサイクルを意識する必要のない作りなので、こっちの方がシンプルでいいかなぁと思っています。
実装はちょっと複雑になっていますが。。。

testOptions in Test が結構便利ですよ、というエントリでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?