Scrivere test utilizzando un client simulato

Scopri come creare stub delle implementazioni dei client reali per inserire un mock per i test delle unità. L'utilizzo di un client mock con le Google Cloud librerie client per Rust consente di scrivere test delle unità controllati e affidabili che non effettuano chiamate di rete né comportano addebiti di fatturazione.

Dipendenze

Sono disponibili diversi framework di mocking per Rust. Questa guida utilizza mockall. Aggiungilo come dipendenza di sviluppo:

cargo add --dev mockall

Inoltre, questa guida utilizza il client Speech per semplificare la comprensione degli esempi (ma questi concetti si applicano a tutti i client).

Aggiungi le dipendenze richieste al file Cargo.toml:

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

Creare un mock di un client

Per testare il codice con un client mock, definisci una struct mock, configuri il comportamento previsto per lo scenario di test e poi inserisci il mock nella logica dell'applicazione. L'esempio seguente illustra questo flusso di lavoro.

Innanzitutto, aggiungi le istruzioni use per semplificare il codice:

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

Supponiamo che l'applicazione abbia una funzione che utilizza il client Speech per chiamare GetRecognizer, impostare il campo name della richiesta ed elaborare la risposta del 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)
}

Puoi testare il modo in cui l'applicazione gestisce le diverse risposte del servizio.

Poi, definisci la struct mock. Questa struct implementa il speech::stub::Speech tratto.

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

Crea un'istanza del mock. Tieni presente che la mockall::mock! macro antepone un Mock prefisso al nome della struct definita in precedenza.

let mut mock = MockSpeech::new();

Imposta le aspettative sul mock. Ad esempio, prevedi che il codice chiami GetRecognizer con un nome specifico e simuli una risposta positiva dal servizio.

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

Crea un client Speech utilizzando il mock:

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

Chiama la funzione:

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

Verifica i risultati:

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

Simulare errori

La simulazione degli errori è simile alla simulazione dei successi. Per simulare un errore, modifica il risultato restituito dal 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))
});

Un client creato con from_stub() non ha un loop di nuovi tentativi interno; restituisce tutti gli errori dello stub direttamente all'applicazione.

Passaggi successivi

Per visualizzare il codice completo di questa guida, consulta il file di origine nel repository google-cloud-rust su GitHub.