Menulis pengujian menggunakan klien tiruan

Pelajari cara membuat stub implementasi klien sebenarnya untuk menyuntikkan mock untuk pengujian unit. Menggunakan klien mock dengan Google Cloud Client Libraries for Rust memungkinkan Anda menulis pengujian unit yang terkontrol dan andal yang tidak melakukan panggilan jaringan atau menimbulkan biaya penagihan.

Dependensi

Ada beberapa framework mocking yang tersedia untuk Rust. Panduan ini menggunakan mockall. Tambahkan sebagai dependensi pengembangan:

cargo add --dev mockall

Selain itu, panduan ini menggunakan klien Speech untuk memudahkan contoh diikuti (tetapi konsep ini berlaku untuk semua klien).

Tambahkan dependensi yang diperlukan ke file Cargo.toml Anda:

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

Membuat mock klien

Untuk menguji kode Anda dengan klien mock, Anda menentukan struct mock, mengonfigurasi perilaku yang diharapkan untuk skenario pengujian, lalu menyuntikkan mock tersebut ke dalam logika aplikasi Anda. Contoh berikut menunjukkan alur kerja ini.

Pertama, tambahkan pernyataan use untuk menyederhanakan kode:

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

Asumsikan aplikasi memiliki fungsi yang menggunakan klien Speech untuk memanggil GetRecognizer, menetapkan kolom name permintaan, dan memproses respons server.

// 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)
}

Anda dapat menguji cara aplikasi menangani berbagai respons dari layanan.

Selanjutnya, tentukan struct mock. Struct ini mengimplementasikan the speech::stub::Speech trait.

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>>;
    }
}

Buat instance mock. Perhatikan bahwa makro mockall::mock! menambahkan awalan Mock ke nama struct yang ditentukan sebelumnya.

let mut mock = MockSpeech::new();

Tetapkan ekspektasi pada mock. Misalnya, harapkan kode untuk memanggil GetRecognizer dengan nama tertentu dan simulasikan respons yang berhasil dari layanan.

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"),
        ))
    });

Buat klien Speech menggunakan mock:

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

Memanggil fungsi:

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

Verifikasi hasilnya:

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

Menyimulasikan error

Menyimulasikan error mirip dengan menyimulasikan keberhasilan. Untuk menyimulasikan error, ubah hasil yang ditampilkan oleh mock.

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))
});

Klien yang dibuat dengan from_stub() tidak memiliki loop coba lagi internal; klien ini menampilkan semua error dari stub langsung ke aplikasi.

Langkah berikutnya

Untuk melihat kode lengkap dari panduan ini, lihat file sumber di repositori google-cloud-rust di GitHub.