

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Pruebas unitarias con `aws-smithy-mocks` el AWS SDK para Rust
<a name="testing-smithy-mocks"></a>

 AWS SDK para Rust Proporciona varios enfoques para probar el código con Servicios de AWS el que interactúa. En este tema se describe cómo utilizar la caja [https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/](https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/), que ofrece una forma sencilla a la vez que eficaz de simular las respuestas del cliente AWS SDK para fines de prueba.

## Descripción general de
<a name="overview-smithy-mock"></a>

Al escribir pruebas para el código que se utiliza Servicios de AWS, a menudo se quiere evitar realizar llamadas de red reales. La caja `aws-smithy-mocks` proporciona una solución al permitirle:
+ Crear reglas simuladas que definan cómo debe responder el SDK a solicitudes específicas.
+ Devolver diferentes tipos de respuestas (éxitos, errores, respuestas HTTP).
+ Hacer coincidir las solicitudes en función de sus propiedades.
+ Definir secuencias de respuestas para probar el comportamiento de los reintentos.
+ Verificar que las reglas se hayan utilizado según lo previsto.

## Incorporación de la dependencia
<a name="dependency-smithy-mock"></a>

En una línea de comandos del directorio del proyecto, agregue la caja [https://crates.io/crates/aws-smithy-mocks](https://crates.io/crates/aws-smithy-mocks) como una dependencia:

```
$ cargo add --dev aws-smithy-mocks
```

Al usar la [opción](https://doc.rust-lang.org/cargo/commands/cargo-add.html) `--dev`, se agrega la caja a la sección `[dev-dependencies]` del archivo `Cargo.toml`. Como [dependencia de desarrollo](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies), no se compila ni se incluye en el binario final que se utiliza para el código de producción.

Este código de ejemplo también usa Amazon Simple Storage Service como ejemplo Servicio de AWS y requiere una función`test-util`.

```
$ cargo add aws-sdk-s3 --features test-util
```

De esta forma, se agrega la caja a la sección `[dependencies]` del archivo `Cargo.toml`.

## Uso básico
<a name="basic-smithy-mocks"></a>

 A continuación, se muestra un ejemplo sencillo de cómo usar `aws-smithy-mocks` para probar código que interactúa con Amazon Simple Storage Service (Amazon S3):

```
use aws_sdk_s3::operation::get_object::GetObjectOutput;
use aws_sdk_s3::primitives::ByteStream;
use aws_smithy_mocks::{mock, mock_client};

#[tokio::test]
async fn test_s3_get_object() {
    // Create a rule that returns a successful response
    let get_object_rule = mock!(aws_sdk_s3::Client::get_object)
        .then_output(|| {
            GetObjectOutput::builder()
                .body(ByteStream::from_static(b"test-content"))
                .build()
        });

    // Create a mocked client with the rule
    let s3 = mock_client!(aws_sdk_s3, [&get_object_rule]);

    // Use the client as you would normally
    let result = s3
        .get_object()
        .bucket("test-bucket")
        .key("test-key")
        .send()
        .await
        .expect("success response");

    // Verify the response
    let data = result.body.collect().await.expect("successful read").to_vec();
    assert_eq!(data, b"test-content");

    // Verify the rule was used
    assert_eq!(get_object_rule.num_calls(), 1);
}
```

## Creación de reglas simuladas
<a name="creating-rules-smithy-mocks"></a>

Las reglas se crean mediante la macro `mock!`, que toma una operación de cliente como argumento. A continuación, puede configurar el comportamiento de la regla. 

### Coincidencia de solicitudes
<a name="matching-requests-smithy-mocks"></a>

 Puede hacer que las reglas sean más específicas haciendo coincidir las propiedades de las solicitudes:

```
let rule = mock!(Client::get_object)
    .match_requests(|req| req.bucket() == Some("test-bucket") && req.key() == Some("test-key"))
    .then_output(|| {
        GetObjectOutput::builder()
            .body(ByteStream::from_static(b"test-content"))
            .build()
    });
```

### Tipos de respuestas diferentes
<a name="diff-response-smithy-mocks"></a>

Puede devolver diferentes tipos de respuestas:

```
// Return a successful response
let success_rule = mock!(Client::get_object)
    .then_output(|| GetObjectOutput::builder().build());

// Return an error
let error_rule = mock!(Client::get_object)
    .then_error(|| GetObjectError::NoSuchKey(NoSuchKey::builder().build()));

// Return a specific HTTP response
let http_rule = mock!(Client::get_object)
    .then_http_response(|| {
        HttpResponse::new(
            StatusCode::try_from(503).unwrap(),
            SdkBody::from("service unavailable")
        )
    });
```

## Prueba del comportamiento de los reintentos
<a name="testing-retry-behavior-smithy-mocks"></a>

Una de las características más potentes de `aws-smithy-mocks` es la capacidad de probar el comportamiento de los reintentos mediante la definición de secuencias de respuestas:

```
// Create a rule that returns 503 twice, then succeeds
let retry_rule = mock!(aws_sdk_s3::Client::get_object)
    .sequence()
    .http_status(503, None)                          // First call returns 503
    .http_status(503, None)                          // Second call returns 503
    .output(|| GetObjectOutput::builder().build())   // Third call succeeds
    .build();

// With repetition using times()
let retry_rule = mock!(Client::get_object)
    .sequence()
    .http_status(503, None)
    .times(2)                                        // First two calls return 503
    .output(|| GetObjectOutput::builder().build())   // Third call succeeds
    .build();
```

## Modos de reglas
<a name="rule-modes-smithy-mocks"></a>

Puede controlar cómo coinciden y se aplican las reglas mediante los modos de regla:

```
// Sequential mode: Rules are tried in order, and when a rule is exhausted, the next rule is used
let client = mock_client!(aws_sdk_s3, RuleMode::Sequential, [&rule1, &rule2]);

// MatchAny mode: The first matching rule is used, regardless of order
let client = mock_client!(aws_sdk_s3, RuleMode::MatchAny, [&rule1, &rule2]);
```

## Ejemplo: prueba del comportamiento de los reintentos
<a name="example-retry-smithy-mocks"></a>

Este es un ejemplo más completo que muestra cómo probar el comportamiento de los reintentos:

```
use aws_sdk_s3::operation::get_object::GetObjectOutput;
use aws_sdk_s3::config::RetryConfig;
use aws_sdk_s3::primitives::ByteStream;
use aws_smithy_mocks::{mock, mock_client, RuleMode};

#[tokio::test]
async fn test_retry_behavior() {
    // Create a rule that returns 503 twice, then succeeds
    let retry_rule = mock!(aws_sdk_s3::Client::get_object)
        .sequence()
        .http_status(503, None)
        .times(2)
        .output(|| GetObjectOutput::builder()
            .body(ByteStream::from_static(b"success"))
            .build())
        .build();

    // Create a mocked client with the rule and custom retry configuration
    let s3 = mock_client!(
        aws_sdk_s3,
        RuleMode::Sequential,
        [&retry_rule],
        |client_builder| {
            client_builder.retry_config(RetryConfig::standard().with_max_attempts(3))
        }
    );

    // This should succeed after two retries
    let result = s3
        .get_object()
        .bucket("test-bucket")
        .key("test-key")
        .send()
        .await
        .expect("success after retries");

    // Verify the response
    let data = result.body.collect().await.expect("successful read").to_vec();
    assert_eq!(data, b"success");

    // Verify all responses were used
    assert_eq!(retry_rule.num_calls(), 3);
}
```

## Ejemplo: diferentes respuestas según los parámetros de solicitud
<a name="example-request-param-smithy-mocks"></a>

También puede crear reglas que devuelvan diferentes respuestas en función de los parámetros de solicitud:

```
use aws_sdk_s3::operation::get_object::{GetObjectOutput, GetObjectError};
use aws_sdk_s3::types::error::NoSuchKey;
use aws_sdk_s3::Client;
use aws_sdk_s3::primitives::ByteStream;
use aws_smithy_mocks::{mock, mock_client, RuleMode};

#[tokio::test]
async fn test_different_responses() {
    // Create rules for different request parameters
    let exists_rule = mock!(Client::get_object)
        .match_requests(|req| req.bucket() == Some("test-bucket") && req.key() == Some("exists"))
        .sequence()
        .output(|| GetObjectOutput::builder()
            .body(ByteStream::from_static(b"found"))
            .build())
        .build();

    let not_exists_rule = mock!(Client::get_object)
        .match_requests(|req| req.bucket() == Some("test-bucket") && req.key() == Some("not-exists"))
        .sequence()
        .error(|| GetObjectError::NoSuchKey(NoSuchKey::builder().build()))
        .build();

    // Create a mocked client with the rules in MatchAny mode
    let s3 = mock_client!(aws_sdk_s3, RuleMode::MatchAny, [&exists_rule, &not_exists_rule]);

    // Test the "exists" case
    let result1 = s3
        .get_object()
        .bucket("test-bucket")
        .key("exists")
        .send()
        .await
        .expect("object exists");

    let data = result1.body.collect().await.expect("successful read").to_vec();
    assert_eq!(data, b"found");

    // Test the "not-exists" case
    let result2 = s3
        .get_object()
        .bucket("test-bucket")
        .key("not-exists")
        .send()
        .await;

    assert!(result2.is_err());
    assert!(matches!(result2.unwrap_err().into_service_error(),
                    GetObjectError::NoSuchKey(_)));
}
```

## Prácticas recomendadas
<a name="best-practices-smithy-mocks"></a>

Cuando se usa `aws-smithy-mocks` para realizar pruebas.

1.  Coincidencia de solicitudes específicas: utilice `match_requests()` para asegurarse de que las reglas solo se aplican a las solicitudes previstas, en particular con `RuleMode:::MatchAny`.

1.  Verificación del uso de las reglas: compruebe `rule.num_calls()` para asegurarse de que las reglas se hayan utilizado realmente.

1.  Prueba de la gestión de errores: cree reglas que devuelvan errores para comprobar cómo gestiona el código los errores.

1.  Prueba de la lógica de reintentos: utilice secuencias de respuesta para comprobar que el código gestiona correctamente cualquier clasificador de reintentos personalizado u otro comportamiento de los reintentos.

1. Centrado en las pruebas: cree pruebas independientes para diferentes escenarios en lugar de tratar de abarcar todo en una sola prueba.