モック クライアントを使用してテストを作成する

実際のクライアント実装をスタブして、単体テスト用のモックを挿入する方法を学習します。 Google Cloud Client Libraries for Rust でモック クライアントを使用すると、ネットワーク呼び出しを行わず、課金が発生しない、制御された信頼性の高い単体テストを作成できます。

依存関係

Rust にはいくつかのモック フレームワークがあります。このガイドでは mockall を使用します。開発依存関係として追加します。

cargo add --dev mockall

また、このガイドでは、例をわかりやすくするために Speech クライアントを使用しています(ただし、これらのコンセプトはすべてのクライアントに適用されます)。

必要な依存関係を Cargo.toml ファイルに追加します。

cargo add google-cloud-speech-v2 google-cloud-lro

クライアントをモックする

モック クライアントを使用してコードをテストするには、モック構造体を定義し、テスト シナリオの想定される動作を構成してから、そのモックをアプリケーション ロジックに挿入します。次の例は、このワークフローを示しています。

まず、use ステートメントを追加してコードを簡素化します。

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

アプリケーションには、Speech クライアントを使用して GetRecognizer を呼び出し、リクエストの name フィールドを設定して、サーバー レスポンスを処理する関数があるとします。

// An example application function.
//
// It makes an RPC, setting some field. In this case, it is the `GetRecognizer`
// RPC, setting the name field.
//
// It processes the response from the server. In this case, it extracts the
// display name of the recognizer.
async fn my_application_function(client: &speech::client::Speech) -> gax::Result<String> {
    client
        .get_recognizer()
        .set_name("invalid-test-recognizer")
        .send()
        .await
        .map(|r| r.display_name)
}

アプリケーションがサービスからのさまざまなレスポンスをどのように処理するかをテストできます。

次に、モック構造体を定義します。この構造体は speech::stub::Speech トレイトを実装します。

mockall::mock! {
    #[derive(Debug)]
    Speech {}
    impl speech::stub::Speech for Speech {
        async fn get_recognizer(&self, req: speech::model::GetRecognizerRequest, _options: gax::options::RequestOptions) -> gax::Result<gax::response::Response<speech::model::Recognizer>>;
    }
}

モックのインスタンスを作成します。mockall::mock! マクロは、以前に定義した構造体の名前の前に Mock 接頭辞を付加します。

let mut mock = MockSpeech::new();

モックアップの期待値を設定します。たとえば、コードが特定の名前で GetRecognizer を呼び出し、サービスからの成功レスポンスをシミュレートすることを想定します。

mock.expect_get_recognizer()
    .withf(move |r, _|
        // Optionally, verify fields in the request.
        r.name == "invalid-test-recognizer")
    .return_once(|_, _| {
        Ok(gax::response::Response::from(
            speech::model::Recognizer::new().set_display_name("test-display-name"),
        ))
    });

モックを使用して Speech クライアントを作成します。

let client = speech::client::Speech::from_stub(mock);

関数を呼び出す

let display_name = my_application_function(&client).await?;

結果を確認します。

assert_eq!(display_name, "test-display-name");

エラーをシミュレートする

エラーのシミュレーションは、成功のシミュレーションと似ています。エラーをシミュレートするには、モックによって返される結果を変更します。

mock.expect_get_recognizer().return_once(|_, _| {
    // This time, return an error.
    use gax::error::Error;
    use gax::error::rpc::{Code, Status};
    let status = Status::default()
        .set_code(Code::NotFound)
        .set_message("Resource not found");
    Err(Error::service(status))
});

from_stub() で構築されたクライアントには内部再試行ループがありません。スタブからのすべてのエラーをアプリケーションに直接返します。

次のステップ

このガイドの完全なコードについては、GitHub の google-cloud-rust リポジトリにあるソースファイルをご覧ください。