Escrever testes usando um cliente simulado

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

Dependências

Há várias estruturas de simulação disponíveis para Rust. Este guia usa mockall. Adicione-o 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 o código com um cliente simulado, defina uma struct simulada, configure o comportamento esperado para o cenário de teste e injete esse simulacro 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 struct simulada. Essa struct implementa a speech::stub::Speech característica.

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. Observe que a mockall::mock! macro anexa um Mock prefixo ao nome da struct definida anteriormente.

let mut mock = MockSpeech::new();

Defina as expectativas no simulacro. 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

A simulação de erros é semelhante à simulação de 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 repetição 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 google-cloud-rust repositório no GitHub (em inglês).