Escribe pruebas con un cliente simulado

Aprende a crear stubs de implementaciones de clientes reales para insertar un objeto simulado para las prueba de unidades. Usar un cliente simulado con las Google Cloud bibliotecas cliente para Rust te permite escribir pruebas de unidades controladas y confiables que no realizan llamadas de red ni generan cargos de facturación.

Dependencias

Hay varios frameworks de simulación disponibles para Rust. En esta guía, se usa mockall. Agrégalo como una dependencia de desarrollo:

cargo add --dev mockall

Además, en esta guía, se usa el cliente Speech para que los ejemplos sean más fáciles de seguir (pero estos conceptos se aplican a todos los clientes).

Agrega las dependencias necesarias a tu archivo Cargo.toml:

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

Cómo simular un cliente

Para probar tu código con un cliente simulado, define una estructura simulada, configura su comportamiento esperado para tu situación de prueba y, luego, inyecta ese simulador en la lógica de tu aplicación. En el siguiente ejemplo, se muestra este flujo de trabajo.

Primero, agrega instrucciones use para simplificar el código:

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

Supón que la aplicación tiene una función que usa el cliente Speech para llamar a GetRecognizer, establecer el campo name de la solicitud y procesar la respuesta del servidor.

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

Puedes probar cómo la aplicación controla diferentes respuestas del servicio.

A continuación, define la estructura simulada. Este struct implementa el rasgo 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>>;
    }
}

Crea una instancia de la simulación. Ten en cuenta que la macro mockall::mock! antepone un prefijo Mock al nombre de la estructura definida anteriormente.

let mut mock = MockSpeech::new();

Establece expectativas sobre la simulación. Por ejemplo, espera que el código llame a GetRecognizer con un nombre en particular y simula una respuesta exitosa del servicio.

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 cliente Speech con el simulador:

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

Llama a la función:

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

Verifica los resultados:

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

Simula errores

Simular errores es similar a simular éxitos. Para simular un error, modifica el resultado que devuelve el objeto simulado.

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 cliente compilado con from_stub() no tiene un bucle interno de reintentos; devuelve todos los errores del stub directamente a la aplicación.

Próximos pasos

Para ver el código completo de esta guía, consulta el archivo fuente en el repositorio google-cloud-rust en GitHub.