Escrever testes usando um cliente simulado

Saiba como criar stubs de implementações de clientes reais para injetar um simulacro em teste de unidade. Usar um cliente simulado com as bibliotecas de cliente do Google Cloud para Rust permite escrever testes de unidade controlados e confiáveis que não fazem chamadas de rede nem geram custos de faturamento.

Dependências

Há vários frameworks de simulação disponíveis para Rust. Este guia usa mockall. Adicione como uma dependência de desenvolvimento:

cargo add --dev mockall

Além disso, este guia usa o cliente Speech para facilitar o acompanhamento dos exemplos, mas esses conceitos se aplicam a todos os clientes.

Adicione as dependências necessárias ao arquivo Cargo.toml:

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

Simular um cliente

Para testar seu código com um cliente simulado, defina uma struct simulada, configure o comportamento esperado dela para seu cenário de teste e injete essa simulação na lógica do aplicativo. O exemplo a seguir demonstra esse fluxo de trabalho.

Primeiro, adicione instruções use para simplificar o código:

use google_cloud_gax as gax;
use google_cloud_speech_v2 as speech;

Suponha que o aplicativo tenha uma função que usa o cliente Speech para chamar GetRecognizer, definindo o campo name da solicitação e processando a resposta do 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)
}

É possível testar como o aplicativo processa diferentes respostas do serviço.

Em seguida, defina a estrutura simulada. Essa struct implementa a característica 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>>;
    }
}

Crie uma instância do simulacro. A macro mockall::mock! adiciona um prefixo Mock ao nome da estrutura definida anteriormente.

let mut mock = MockSpeech::new();

Defina expectativas no simulado. Por exemplo, espere que o código chame GetRecognizer com um nome específico e simule uma resposta bem-sucedida do serviço.

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

Crie um cliente Speech usando o simulacro:

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

Como chamar a função:

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

Verifique os resultados:

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

Simular erros

Simular erros é semelhante a simular sucessos. Para simular um erro, modifique o resultado retornado pelo simulacro.

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

Um cliente criado com from_stub() não tem um loop de novas tentativas interno. Ele retorna todos os erros do stub diretamente para o aplicativo.

Próximas etapas

Para conferir o código completo deste guia, consulte o arquivo de origem no repositório google-cloud-rust no GitHub.