כתיבת בדיקות באמצעות לקוח מדומה

כאן מוסבר איך ליצור stub של הטמעות אמיתיות של לקוחות כדי להחדיר mock לבדיקות יחידה. שימוש בלקוח מדומה עם Google Cloud ספריות הלקוח של Rust מאפשר לכם לכתוב בדיקות יחידה מהימנות ומבוקרות שלא מבצעות קריאות לרשת ולא גוררות חיובים.

תלויות

יש כמה מסגרות עבודה ל-mocking שזמינות ל-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>>;
    }
}

יוצרים מופע של ה-mock. שימו לב שמאקרו 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 באמצעות ה-mock:

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

מפעילים את הפונקציה:

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

מאמתים את התוצאות:

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

סימולציה של שגיאות

סימולציית שגיאות דומה לסימולציית הצלחות. כדי לדמות שגיאה, משנים את התוצאה שמוחזרת על ידי ה-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))
});

ללקוח שנבנה באמצעות from_stub() אין לולאת ניסיון חוזר פנימית, והוא מחזיר את כל השגיאות מה-stub ישירות לאפליקציה.

השלבים הבאים

כדי לראות את הקוד המלא מהמדריך הזה, אפשר לעיין בקובץ המקור במאגר google-cloud-rust ב-GitHub.