使用模擬用戶端編寫測試

瞭解如何將實際用戶端實作項目虛設常式化,以便插入模擬項目進行單元測試。使用 Google Cloud 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 存放區中的來源檔案