

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à.

# 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