asyncなライブラリー関数のテストを書く
今回解決したい問題
reqwestのドキュメント の最初のサンプルをテスト実行することを考えます。
|
|
まず Cargo.toml に依存関係を追加して、
cargo new --lib test-async
cd test-async
cargo add reqwest
冒頭のコードを実行する関数を作ります。
|
|
cargo check を実行すると次のエラーが出ます。
only allowed inside `async` functions and blocks
関数を async で定義することでこのエラーを解消します。
|
|
するとまた別のエラーが出ます。
this function should return `Result` or `Option` to accept `?`
戻り値の型を Result (もしくは Option)にする必要があります。 ところで正常時の戻り値は自分で制御できますが、エラー時は ? が制御しているので型がわかりません。とりあえず () でおいて修正します。
|
|
そうすると当然
`?` couldn't convert the error to `()`
というエラーが出ます。 そしてよく見るともう少し詳細な出力があります。
the trait `From<reqwest::Error>` is not implemented for `()`, which is required by `Result<(), ()>: FromResidual<Result<Infallible, reqwest::Error>>`
このメッセージから察するに、どうもエラーの型は reqwest::Error っぽいです。これで書き換えてみます。
|
|
これでやっとエラーがなくなりました。
この関数に対してテストコードを書いていきましょう。 自動生成されていたテンプレートを書き換えてみます。
|
|
cargo test を実行すると次のエラーメッセージ。
help: consider `await`ing on the `Future` and calling the method on its `Output` let result = my_func().await.unwrap(); ++++++
言われるまま .await を付けてみます。
|
|
すると次はこんなエラーが。
`await` is only allowed inside `async` functions and blocks
await が使えるのは async な関数の中でだけ、と。
じゃあ async 付ければ良いのか、と
|
|
すると、
async functions cannot be used for tests
テストの関数は async にできない、と。じゃあどうすれば良いんだというのがわからない、というのが今回の問題です。
対応
答えは、「テスト実行用に非同期ランタイムを導入する」ということのようです。
今回は tokio を利用してみます。 ドキュメントを読むとテスト用の説明が書いてあります。 今回利用する tokio であればこのあたり:
というわけでやってみます。
cargo add --dev tokio --features='macros'
で dev-dependencies に tokio を追加し、テストコードを次のように書き換えます。
|
|
cargo test を実行すると…テストが pass しました!
今回のコード: