

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Generieren Sie automatisch Mocks mithilfe `mockall` des AWS SDK für Rust
<a name="testing-automock"></a>

Das AWS SDK für Rust bietet mehrere Ansätze zum Testen Ihres Codes, der mit AWS-Services interagiert. Sie können die meisten Scheinimplementierungen, die Ihre Tests benötigen, automatisch generieren, indem Sie die beliebten `[automock](https://docs.rs/mockall/latest/mockall/attr.automock.html)` aus der `[mockall](https://docs.rs/mockall/latest/mockall)` Kiste verwenden.

In diesem Beispiel wird eine benutzerdefinierte Methode namens getestet. `determine_prefix_file_size()` Diese Methode ruft eine benutzerdefinierte `list_objects()` Wrapper-Methode auf, die Amazon S3 aufruft. Durch Spott kann die `determine_prefix_file_size()` Methode getestet werden`list_objects()`, ohne Amazon S3 tatsächlich zu kontaktieren. 

1. Fügen Sie in einer Befehlszeile für Ihr Projektverzeichnis die `[mockall](https://docs.rs/mockall/latest/mockall)` Kiste als Abhängigkeit hinzu:

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

   Wenn Sie die `--dev` [Option](https://doc.rust-lang.org/cargo/commands/cargo-add.html) verwenden, wird die Kiste dem `[dev-dependencies]` Abschnitt Ihrer `Cargo.toml` Datei hinzugefügt. Da es sich um eine [Entwicklungsabhängigkeit](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies) handelt, wird sie nicht kompiliert und nicht in Ihre endgültige Binärdatei aufgenommen, die für den Produktionscode verwendet wird.

   In diesem Beispielcode wird auch Amazon Simple Storage Service als Beispiel verwendet AWS-Service.

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

   Dadurch wird die Kiste dem `[dependencies]` Abschnitt Ihrer `Cargo.toml` Datei hinzugefügt.

1. Fügen Sie das `automock` Modul aus der `mockall` Kiste hinzu. 

   Schließen Sie auch alle anderen Bibliotheken ein AWS-Service , die sich auf das beziehen, das Sie testen, in diesem Fall Amazon S3.

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

1. Fügen Sie als Nächstes Code hinzu, der bestimmt, welche von zwei Implementierungen der Amazon S3 S3-Wrapper-Struktur der Anwendung verwendet werden soll. 
   + Der echte, der für den Zugriff auf Amazon S3 über das Netzwerk geschrieben wurde.
   + Die Scheinimplementierung, generiert von`mockall`.

   In diesem Beispiel erhält die ausgewählte Datei den Namen`S3`. Die Auswahl ist abhängig von dem `test` Attribut:

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

1. Die `S3Impl` Struktur ist die Implementierung der Amazon S3 S3-Wrapper-Struktur, an die tatsächlich Anfragen gesendet AWS werden.
   + Wenn das Testen aktiviert ist, wird dieser Code nicht verwendet, da die Anfrage an den Mock gesendet wird und nicht AWS. Das `dead_code` Attribut weist den Linter an, kein Problem zu melden, wenn der `S3Impl` Typ nicht verwendet wird.
   +  Die Bedingung `#[cfg_attr(test, automock)]` gibt an, dass das `automock` Attribut gesetzt werden sollte, wenn das Testen aktiviert ist. Dies weist darauf `mockall` hin, `S3Impl` dass ein Modell generiert werden soll, das benannt wird`Mock{{S3Impl}}`.
   + In diesem Beispiel ist die `list_objects()` Methode der Aufruf, den Sie verspotten möchten. `automock`erstellt automatisch eine `expect_{{list_objects()}}` Methode für Sie. 

   ```
   #[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. Erstellen Sie die Testfunktionen in einem Modul mit dem Namen`test`.
   + Die Bedingung `#[cfg(test)]` gibt an, dass das Testmodul erstellt werden `mockall` soll, wenn das `test` `true` Attribut

   ```
   #[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);
       }
   }
   ```
   + Jeder Test verwendet`let mut mock = MockS3Impl::default();`, um eine `mock` Instanz von zu erstellen`MockS3Impl`. 
   + Es verwendet die `expect_list_objects()` Methode des Mocks (die automatisch von erstellt wurde`automock`), um das erwartete Ergebnis festzulegen, wenn die `list_objects()` Methode an anderer Stelle im Code verwendet wird.
   + Nachdem die Erwartungen festgelegt wurden, werden diese verwendet, um die Funktion durch Aufrufen zu testen`determine_prefix_file_size()`. Der zurückgegebene Wert wird anhand einer Assertion überprüft, um zu bestätigen, dass er korrekt ist.

1. Die `determine_prefix_file_size()` Funktion verwendet den Amazon S3 S3-Wrapper, um die Größe der Präfixdatei abzurufen:

   ```
   #[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)
   }
   ```

Der Typ `S3` wird verwendet, um das verpackte SDK für Rust-Funktionen aufzurufen, um beide Funktionen zu unterstützen, `S3Impl` und `MockS3Impl` wenn HTTP-Anfragen gestellt werden. Der automatisch generierte Mock `mockall` meldet alle Testfehler, wenn das Testen aktiviert ist.

[Den vollständigen Code für diese Beispiele finden](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rustv1/examples/testing) Sie unter GitHub.