

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Aggiungere il test unitario alla tua AWS applicazione SDK per Rust
<a name="testing"></a>

Sebbene ci siano molti modi per implementare i test unitari nel AWS SDK per Rust progetto, ve ne sono alcuni che consigliamo:
+ [Test unitario utilizzando `mockall`](testing-automock.md)— Utilizzalo `automock` from the `mockall` crate per generare ed eseguire automaticamente i test.
+ [Replay statico](testing-replay.md)— Usa il runtime di AWS Smithy `StaticReplayClient` per creare un falso client HTTP che può essere usato al posto del client HTTP standard che viene normalmente utilizzato da. Servizi AWS Questo client restituisce le risposte HTTP specificate anziché comunicare con il servizio tramite la rete, in modo che i test ottengano dati noti a scopo di test.
+ [Test unitario utilizzando `aws-smithy-mocks`](testing-smithy-mocks.md)— Utilizza «`mock`and `mock_client` from the `aws-smithy-mocks` crate» per simulare le risposte dei client AWS SDK e creare regole fittizie che definiscono come l'SDK deve rispondere a richieste specifiche.

# Genera automaticamente dei mock utilizzando l'`mockall` AWS SDK per Rust
<a name="testing-automock"></a>

 AWS SDK per Rust Fornisce diversi approcci per testare il codice con cui interagisce. Servizi AWS Puoi generare automaticamente la maggior parte delle implementazioni fittizie di cui i tuoi test hanno bisogno utilizzando il popolare programma `[automock](https://docs.rs/mockall/latest/mockall/attr.automock.html)` from the crate. `[mockall](https://docs.rs/mockall/latest/mockall)`

Questo esempio verifica un metodo personalizzato chiamato. `determine_prefix_file_size()` Questo metodo chiama un metodo `list_objects()` wrapper personalizzato che chiama Amazon S3. Simulando`list_objects()`, il `determine_prefix_file_size()` metodo può essere testato senza contattare effettivamente Amazon S3. 

1. In un prompt dei comandi per la directory del tuo progetto, aggiungi la `[mockall](https://docs.rs/mockall/latest/mockall)` cassa come dipendenza:

   ```
   $ cargo add --dev mockall
   ```

   L'utilizzo dell'`--dev`[opzione](https://doc.rust-lang.org/cargo/commands/cargo-add.html) aggiunge la cassa alla `[dev-dependencies]` sezione del file. `Cargo.toml` Come [dipendenza di sviluppo](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies), non viene compilato e incluso nel file binario finale utilizzato per il codice di produzione.

   Questo codice di esempio utilizza anche Amazon Simple Storage Service come esempio Servizio AWS.

   ```
   $ cargo add aws-sdk-s3
   ```

   In questo modo la cassa viene aggiunta alla `[dependencies]` sezione del `Cargo.toml` file.

1. Includi il `automock` modulo dalla `mockall` cassa. 

   Includi anche qualsiasi altra libreria correlata a Servizio AWS quella che stai testando, in questo caso Amazon S3.

   ```
   use aws_sdk_s3 as s3;
   #[allow(unused_imports)]
   use mockall::automock;
   
   use s3::operation::list_objects_v2::{ListObjectsV2Error, ListObjectsV2Output};
   ```

1. Quindi, aggiungi il codice che determina quale delle due implementazioni della struttura wrapper Amazon S3 dell'applicazione utilizzare. 
   + Quella vera scritta per accedere ad Amazon S3 tramite la rete.
   + L'implementazione fittizia generata da. `mockall`

   In questo esempio, a quella selezionata viene assegnato il nome`S3`. La selezione è condizionata in base all'`test`attributo:

   ```
   #[cfg(test)]
   pub use MockS3Impl as S3;
   #[cfg(not(test))]
   pub use S3Impl as S3;
   ```

1. La `S3Impl` struttura è l'implementazione della struttura wrapper di Amazon S3 a cui invia effettivamente le richieste. AWS
   + Quando il test è abilitato, questo codice non viene utilizzato perché la richiesta viene inviata al mock e non. AWS L'`dead_code`attributo dice al linter di non segnalare un problema se il `S3Impl` tipo non viene utilizzato.
   +  Il condizionale `#[cfg_attr(test, automock)]` indica che quando il test è abilitato, l'`automock`attributo deve essere impostato. Questo dice `mockall` di generare un mock a `S3Impl` cui verrà dato un nome. `MockS3Impl`
   + In questo esempio, il `list_objects()` metodo è la chiamata che vuoi deridere. `automock`creerà automaticamente un `expect_list_objects()` metodo per te. 

   ```
   #[allow(dead_code)]
   pub struct S3Impl {
       inner: s3::Client,
   }
   
   #[cfg_attr(test, automock)]
   impl S3Impl {
       #[allow(dead_code)]
       pub fn new(inner: s3::Client) -> Self {
           Self { inner }
       }
   
       #[allow(dead_code)]
       pub async fn list_objects(
           &self,
           bucket: &str,
           prefix: &str,
           continuation_token: Option<String>,
       ) -> Result<ListObjectsV2Output, s3::error::SdkError<ListObjectsV2Error>> {
           self.inner
               .list_objects_v2()
               .bucket(bucket)
               .prefix(prefix)
               .set_continuation_token(continuation_token)
               .send()
               .await
       }
   }
   ```

1. Crea le funzioni di test in un modulo denominato`test`.
   + Il condizionale `#[cfg(test)]` indica che `mockall` dovrebbe creare il modulo di test se l'`test`attributo lo è`true`.

   ```
   #[cfg(test)]
   mod test {
       use super::*;
       use mockall::predicate::eq;
   
       #[tokio::test]
       async fn test_single_page() {
           let mut mock = MockS3Impl::default();
           mock.expect_list_objects()
               .with(eq("test-bucket"), eq("test-prefix"), eq(None))
               .return_once(|_, _, _| {
                   Ok(ListObjectsV2Output::builder()
                       .set_contents(Some(vec![
                           // Mock content for ListObjectsV2 response
                           s3::types::Object::builder().size(5).build(),
                           s3::types::Object::builder().size(2).build(),
                       ]))
                       .build())
               });
   
           // Run the code we want to test with it
           let size = determine_prefix_file_size(mock, "test-bucket", "test-prefix")
               .await
               .unwrap();
   
           // Verify we got the correct total size back
           assert_eq!(7, size);
       }
   
       #[tokio::test]
       async fn test_multiple_pages() {
           // Create the Mock instance with two pages of objects now
           let mut mock = MockS3Impl::default();
           mock.expect_list_objects()
               .with(eq("test-bucket"), eq("test-prefix"), eq(None))
               .return_once(|_, _, _| {
                   Ok(ListObjectsV2Output::builder()
                       .set_contents(Some(vec![
                           // Mock content for ListObjectsV2 response
                           s3::types::Object::builder().size(5).build(),
                           s3::types::Object::builder().size(2).build(),
                       ]))
                       .set_next_continuation_token(Some("next".to_string()))
                       .build())
               });
           mock.expect_list_objects()
               .with(
                   eq("test-bucket"),
                   eq("test-prefix"),
                   eq(Some("next".to_string())),
               )
               .return_once(|_, _, _| {
                   Ok(ListObjectsV2Output::builder()
                       .set_contents(Some(vec![
                           // Mock content for ListObjectsV2 response
                           s3::types::Object::builder().size(3).build(),
                           s3::types::Object::builder().size(9).build(),
                       ]))
                       .build())
               });
   
           // Run the code we want to test with it
           let size = determine_prefix_file_size(mock, "test-bucket", "test-prefix")
               .await
               .unwrap();
   
           assert_eq!(19, size);
       }
   }
   ```
   + Ogni test utilizza `let mut mock = MockS3Impl::default();` per creare un'`mock`istanza di`MockS3Impl`. 
   + Utilizza il `expect_list_objects()` metodo mock's (che è stato creato automaticamente da`automock`) per impostare il risultato previsto per quando il `list_objects()` metodo viene utilizzato altrove nel codice.
   + Dopo aver stabilito le aspettative, le utilizza per testare la funzione `determine_prefix_file_size()` chiamando. Il valore restituito viene controllato per confermare che sia corretto, utilizzando un'asserzione.

1. La `determine_prefix_file_size()` funzione utilizza il wrapper Amazon S3 per ottenere la dimensione del file del prefisso:

   ```
   #[allow(dead_code)]
   pub async fn determine_prefix_file_size(
       // Now we take a reference to our trait object instead of the S3 client
       // s3_list: ListObjectsService,
       s3_list: S3,
       bucket: &str,
       prefix: &str,
   ) -> Result<usize, s3::Error> {
       let mut next_token: Option<String> = None;
       let mut total_size_bytes = 0;
       loop {
           let result = s3_list
               .list_objects(bucket, prefix, next_token.take())
               .await?;
   
           // Add up the file sizes we got back
           for object in result.contents() {
               total_size_bytes += object.size().unwrap_or(0) as usize;
           }
   
           // Handle pagination, and break the loop if there are no more pages
           next_token = result.next_continuation_token.clone();
           if next_token.is_none() {
               break;
           }
       }
       Ok(total_size_bytes)
   }
   ```

Il tipo `S3` viene utilizzato per chiamare le funzioni Wrapped SDK for Rust per supportare entrambe `S3Impl` le funzioni e per effettuare richieste HTTP. `MockS3Impl` Il mock generato automaticamente da `mockall` segnala eventuali errori di test quando il test è abilitato.

È possibile [visualizzare il codice completo per questi esempi](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1/examples/testing) su. GitHub

# Simula il traffico HTTP utilizzando la riproduzione statica nell' AWS SDK per Rust
<a name="testing-replay"></a>

 AWS SDK per Rust Fornisce diversi approcci per testare il codice con cui interagisce. Servizi AWS Questo argomento descrive come utilizzare per `StaticReplayClient` creare un client HTTP falso che può essere utilizzato al posto del client HTTP standard normalmente utilizzato da Servizi AWS. Questo client restituisce le risposte HTTP specificate anziché comunicare con il servizio tramite la rete, in modo che i test ottengano dati noti a scopo di test.

La `aws-smithy-http-client` cassa include una classe di utilità di test denominata. [https://docs.rs/aws-smithy-http-client/latest/aws_smithy_http_client/test_util/struct.StaticReplayClient.html](https://docs.rs/aws-smithy-http-client/latest/aws_smithy_http_client/test_util/struct.StaticReplayClient.html) Questa classe client HTTP può essere specificata al posto del client HTTP predefinito durante la creazione di un Servizio AWS oggetto.

Quando si inizializza`StaticReplayClient`, si fornisce un elenco di coppie di richieste e risposte HTTP come `ReplayEvent` oggetti. Durante l'esecuzione del test, ogni richiesta HTTP viene registrata e il client restituisce la risposta HTTP successiva trovata nella successiva `ReplayEvent` nell'elenco degli eventi come risposta del client HTTP. Ciò consente l'esecuzione del test utilizzando dati noti e senza una connessione di rete.

## Utilizzo della riproduzione statica
<a name="testing-replay-steps"></a>

Per utilizzare la riproduzione statica, non è necessario utilizzare un wrapper. Invece, stabilisci come dovrebbe essere l'effettivo traffico di rete per i dati che verranno utilizzati dal test e fornisci tali dati sul traffico all'utente da utilizzare ogni volta che l'SDK invia una richiesta dal client. `StaticReplayClient` Servizio AWS 

**Nota**  
Esistono diversi modi per raccogliere il traffico di rete previsto, tra cui numerosi analizzatori del traffico di rete AWS CLI e strumenti di analisi dei pacchetti.
+ Crea un elenco di `ReplayEvent` oggetti che specificano le richieste HTTP previste e le risposte che devono essere restituite per esse.
+ Crea un elenco di transazioni `StaticReplayClient` utilizzando l'elenco di transazioni HTTP creato nel passaggio precedente.
+ Crea un oggetto di configurazione per il AWS client, specificandolo `StaticReplayClient` come `Config` oggetto. `http_client`
+ Create l'oggetto Servizio AWS client, utilizzando la configurazione creata nel passaggio precedente.
+ Eseguite le operazioni che desiderate testare utilizzando l'oggetto servizio configurato per utilizzare il`StaticReplayClient`. Ogni volta che l'SDK invia una richiesta API a AWS, viene utilizzata la risposta successiva nell'elenco.
**Nota**  
La risposta successiva nell'elenco viene sempre restituita, anche se la richiesta inviata non corrisponde a quella nel vettore di `ReplayEvent` oggetti.
+ Una volta effettuate tutte le richieste desiderate, chiamate la `StaticReplayClient.assert_requests_match()` funzione per verificare che le richieste inviate dall'SDK corrispondano a quelle nell'elenco degli `ReplayEvent` oggetti.

## Esempio
<a name="testing-replay-example"></a>

Diamo un'occhiata ai test per la stessa `determine_prefix_file_size()` funzione nell'esempio precedente, ma utilizziamo la riproduzione statica anziché la simulazione.

1. In un prompt dei comandi per la directory del progetto, aggiungi la [https://crates.io/crates/aws-smithy-http-client](https://crates.io/crates/aws-smithy-http-client)cassa come dipendenza:

   ```
   $ cargo add --dev aws-smithy-http-client --features test-util
   ```

   L'utilizzo dell'`--dev`[opzione](https://doc.rust-lang.org/cargo/commands/cargo-add.html) aggiunge la cassa alla `[dev-dependencies]` sezione del file. `Cargo.toml` Come [dipendenza di sviluppo](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies), non viene compilato e incluso nel file binario finale utilizzato per il codice di produzione.

   Questo codice di esempio utilizza anche Amazon Simple Storage Service come esempio Servizio AWS.

   ```
   $ cargo add aws-sdk-s3
   ```

   Questo aggiunge la cassa alla `[dependencies]` sezione del `Cargo.toml` file.

1. Nel modulo di codice di test, includi entrambi i tipi di cui avrai bisogno.

   ```
   use aws_smithy_http_client::test_util::{ReplayEvent, StaticReplayClient};
   use aws_sdk_s3::primitives::SdkBody;
   ```

1. Il test inizia creando le `ReplayEvent` strutture che rappresentano ciascuna delle transazioni HTTP che dovrebbero avvenire durante il test. Ogni evento contiene un oggetto di richiesta HTTP e un oggetto di risposta HTTP che rappresentano le informazioni con cui normalmente Servizio AWS risponderebbero. Questi eventi vengono passati in una chiamata a`StaticReplayClient::new()`:

   ```
           let page_1 = ReplayEvent::new(
                   http::Request::builder()
                       .method("GET")
                       .uri("https://test-bucket.s3.us-east-1.amazonaws.com/?list-type=2&prefix=test-prefix")
                       .body(SdkBody::empty())
                       .unwrap(),
                   http::Response::builder()
                       .status(200)
                       .body(SdkBody::from(include_str!("./testing/response_multi_1.xml")))
                       .unwrap(),
               );
           let page_2 = ReplayEvent::new(
                   http::Request::builder()
                       .method("GET")
                       .uri("https://test-bucket.s3.us-east-1.amazonaws.com/?list-type=2&prefix=test-prefix&continuation-token=next")
                       .body(SdkBody::empty())
                       .unwrap(),
                   http::Response::builder()
                       .status(200)
                       .body(SdkBody::from(include_str!("./testing/response_multi_2.xml")))
                       .unwrap(),
               );
           let replay_client = StaticReplayClient::new(vec![page_1, page_2]);
   ```

   Il risultato viene memorizzato in`replay_client`. Rappresenta un client HTTP che può quindi essere utilizzato dall'SDK per Rust specificandolo nella configurazione del client.

1. Per creare il client Amazon S3, chiama la `from_conf()` funzione della classe client per creare il client utilizzando un oggetto di configurazione:

   ```
           let client: s3::Client = s3::Client::from_conf(
               s3::Config::builder()
                   .behavior_version(BehaviorVersion::latest())
                   .credentials_provider(make_s3_test_credentials())
                   .region(s3::config::Region::new("us-east-1"))
                   .http_client(replay_client.clone())
                   .build(),
           );
   ```

   L'oggetto di configurazione viene specificato utilizzando il `http_client()` metodo del generatore e le credenziali vengono specificate utilizzando il metodo. `credentials_provider()` Le credenziali vengono create utilizzando una funzione chiamata`make_s3_test_credentials()`, che restituisce una struttura di credenziali false:

   ```
   fn make_s3_test_credentials() -> s3::config::Credentials {
       s3::config::Credentials::new(
           "ATESTCLIENT",
           "astestsecretkey",
           Some("atestsessiontoken".to_string()),
           None,
           "",
       )
   }
   ```

   Queste credenziali non devono essere valide perché non verranno effettivamente inviate a. AWS

1. Esegui il test chiamando la funzione che deve essere testata. In questo esempio, il nome di quella funzione è`determine_prefix_file_size()`. Il suo primo parametro è l'oggetto client Amazon S3 da utilizzare per le sue richieste. Pertanto, specifica il client creato utilizzando il sistema `StaticReplayClient` in modo che le richieste vengano gestite da quello anziché essere inviate in rete:

   ```
           let size = determine_prefix_file_size(client, "test-bucket", "test-prefix")
               .await
               .unwrap();
   
           assert_eq!(19, size);
   
           replay_client.assert_requests_match(&[]);
   ```

   Al termine della chiamata a, `determine_prefix_file_size()` viene utilizzata un'asserzione per confermare che il valore restituito corrisponde al valore previsto. Quindi, viene chiamata la `assert_requests_match()` funzione del `StaticReplayClient` metodo. Questa funzione analizza le richieste HTTP registrate e conferma che corrispondono tutte a quelle specificate nell'array di `ReplayEvent` oggetti fornito durante la creazione del client di replay.

È possibile [visualizzare il codice completo per questi esempi](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1/examples/testing) su. GitHub

# Test unitario con `aws-smithy-mocks` l' AWS SDK per Rust
<a name="testing-smithy-mocks"></a>

 AWS SDK per Rust Fornisce diversi approcci per testare il codice con cui interagisce. Servizi AWS Questo argomento descrive come utilizzare il [https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/](https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/)crate, che offre un modo semplice ma potente per simulare le risposte dei client AWS SDK a scopo di test.

## Panoramica di
<a name="overview-smithy-mock"></a>

Quando si scrivono test per il codice che utilizza Servizi AWS, spesso si desidera evitare di effettuare chiamate di rete effettive. The `aws-smithy-mocks` crate offre una soluzione che consente di:
+ Crea regole fittizie che definiscono come l'SDK deve rispondere a richieste specifiche.
+ Restituisce diversi tipi di risposte (successo, errore, risposte HTTP).
+ Abbina le richieste in base alle loro proprietà.
+ Definisci sequenze di risposte per testare il comportamento dei tentativi.
+ Verifica che le tue regole siano state utilizzate come previsto.

## Aggiungere la dipendenza
<a name="dependency-smithy-mock"></a>

In un prompt dei comandi per la directory del progetto, aggiungi la [https://crates.io/crates/aws-smithy-mocks](https://crates.io/crates/aws-smithy-mocks)cassa come dipendenza:

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

L'utilizzo dell'`--dev`[opzione](https://doc.rust-lang.org/cargo/commands/cargo-add.html) aggiunge la cassa alla `[dev-dependencies]` sezione del file. `Cargo.toml` Come [dipendenza di sviluppo](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies), non viene compilato e incluso nel file binario finale utilizzato per il codice di produzione.

Questo codice di esempio utilizza anche Amazon Simple Storage Service come Servizio AWS esempio e richiede funzionalità`test-util`.

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

In questo modo la cassa viene aggiunta alla `[dependencies]` sezione del `Cargo.toml` file.

## Utilizzo di base
<a name="basic-smithy-mocks"></a>

 Ecco un semplice esempio di come utilizzare per `aws-smithy-mocks` testare il codice che interagisce 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);
}
```

## Creazione di regole fittizie
<a name="creating-rules-smithy-mocks"></a>

Le regole vengono create utilizzando la `mock!` macro, che accetta come argomento un'operazione client. È quindi possibile configurare il comportamento della regola. 

### Richieste corrispondenti
<a name="matching-requests-smithy-mocks"></a>

 Puoi rendere le regole più specifiche abbinando le proprietà su richiesta:

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

### Diversi tipi di risposta
<a name="diff-response-smithy-mocks"></a>

Puoi restituire diversi tipi di risposte:

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

## Verifica del comportamento dei tentativi
<a name="testing-retry-behavior-smithy-mocks"></a>

Una delle funzionalità più potenti di `aws-smithy-mocks` è la possibilità di testare il comportamento dei tentativi di ripetizione definendo sequenze di risposte:

```
// 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();
```

## Modalità di regole
<a name="rule-modes-smithy-mocks"></a>

È possibile controllare il modo in cui le regole vengono abbinate e applicate utilizzando le modalità di regola:

```
// 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]);
```

## Esempio: verifica del comportamento dei tentativi
<a name="example-retry-smithy-mocks"></a>

Ecco un esempio più completo che mostra come testare il comportamento dei nuovi tentativi:

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

## Esempio: risposte diverse in base ai parametri della richiesta
<a name="example-request-param-smithy-mocks"></a>

Puoi anche creare regole che restituiscono risposte diverse in base ai parametri della richiesta:

```
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(_)));
}
```

## Best practice
<a name="best-practices-smithy-mocks"></a>

Quando si utilizza `aws-smithy-mocks` per il test:

1.  Corrisponde a richieste specifiche: utilizza `match_requests()` questa opzione per garantire che le regole si applichino solo alle richieste previste, in particolare con`RuleMode:::MatchAny`.

1.  Verifica l'utilizzo delle regole: verifica `rule.num_calls()` che le regole siano state effettivamente utilizzate.

1.  Gestione degli errori di test: crea regole che restituiscano errori per verificare come il codice gestisce gli errori.

1.  Verifica la logica dei tentativi: utilizza le sequenze di risposta per verificare che il codice gestisca correttamente eventuali classificatori di tentativi personalizzati o altri comportamenti di ripetizione dei tentativi.

1. Mantieni i test concentrati: crea test separati per scenari diversi anziché cercare di coprire tutto in un unico test.