Rust で Web API クライアントを作成したので、そのテストを実行できるようにこちらの Mockito と言う HTTP モックライブラリを使ってみた。
利用方法
使い方としては、下記の設定をする。 (こちらのドキュメント に書かれている通りだが。。)
- テスト用の URL を用意し、テスト時はそちらに対して、リクエストを投げるようにする
- レスポンスの内容を定義し、そのレスポンスを返して欲しい URL を指定する
テスト用の URL を用意する
これは、下記の通り、フラグを使用して、実際に実行する URL とテスト用の URL をそれぞれ定義すれば良いだけ。
こうすることにより、テスト時にビルドされる場合は、モックの URL に対して、リクエストを投げるようになる。
レスポンス内容を設定する
返して欲しいレスポンスヘッダやボディの値をビルダーバターンのように作成する。
モックを作成する際、header や body を設定し、最後に create
もしくは、 create_for
メソッドを呼ぶことにより設定される。
create
メソッドの場合create
メソッドでモックを作成した場合は、テスト終了後に、remove
メソッドを呼んで、モックの設定を自分で削除しなければならない。 削除しないと別のテストケース実行時にも登録された状態になり、意図しない動作になるため。
create_for
メソッドの場合create_for
は lambda を引数に取り、lambda 内の処理が完了すると、作成したモックの設定を自動的に削除してくれる。
動作内容
どのように動作しているか気になったので、調べてみた。
テスト実行時にローカルに Web サーバーを起動させる。(ポートは 1234) テスト用に設定した URL に対するリクエストは全てローカルに立てた Web サーバーに投げられる。
上記の
create
メソッドもしくは、create_for
メソッドが呼ばれた際、 そのサーバーに対して、指定した URL とレスポンスの内容を登録するリクエストを投げる。サーバー側は、受け取ったモックの情報を保持し、指定された URL に対して、指定したレスポンスを返すようになる。
テスト対象のプログラムがその指定した URL に対してリクエストを投げると、 モックとして登録した内容が返却される。
ハマった点
テストを実行すると、成功したり、失敗したりと安定しなかった。
原因は、Rust のテストはマルチスレッドで実行されるため、モックサーバーの同じ URL に対して、違うレスポンス内容を設定すると、別スレッドで書き換えられた意図しないレスポンスが帰ってくるためだった。 解決策としては、とりあえず以下のように実行するスレッドを 1つにしてみた。
cargo test -- --test-threads=1
まとめ
これで、Web API クライアントのようなネットワーク通信を行う Rust プログラムもテストできるようになった。 このモックは、実際にローカルにサーバーを立てて、レスポンスを定義して、テストを行うライブラリだということがわかった。
ただ、Web API クライアントのテストはできるようになったのだが、マルチスレッドではテストできないのだろうか? テストケースが増えてきた場合は、マルチスレッドで動作させたくなると思う。