

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.

# Hinzufügen von Unit-Tests zu Ihrer AWS SDK für Rust-Anwendung
<a name="testing"></a>

Es gibt zwar viele Möglichkeiten, Unit-Tests in Ihrem AWS SDK für Rust Projekt zu implementieren, wir empfehlen jedoch einige:
+ [Komponententests mit `mockall`](testing-automock.md)— Verwenden Sie es `automock` aus der `mockall` Kiste, um Ihre Tests automatisch zu generieren und auszuführen.
+ [Statische Wiedergabe](testing-replay.md)— Verwenden Sie die AWS Smithy-Runtime's`StaticReplayClient`, um einen gefälschten HTTP-Client zu erstellen, der anstelle des Standard-HTTP-Clients verwendet werden kann, der normalerweise von verwendet wird. AWS-Services Dieser Client gibt die von Ihnen angegebenen HTTP-Antworten zurück, anstatt mit dem Dienst über das Netzwerk zu kommunizieren, sodass Tests bekannte Daten für Testzwecke abrufen.
+ [Unit-Tests mit `aws-smithy-mocks`](testing-smithy-mocks.md)— Verwenden Sie `mock` und `mock_client` aus der `aws-smithy-mocks` Kiste, um Antworten von AWS SDK-Clients nachzuahmen und Scheinregeln zu erstellen, die definieren, wie das SDK auf bestimmte Anfragen reagieren soll.

# 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`MockS3Impl`.
   + 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.

# Simulieren Sie den HTTP-Verkehr mithilfe der statischen Wiedergabe im AWS SDK für Rust
<a name="testing-replay"></a>

Das AWS SDK für Rust bietet mehrere Ansätze zum Testen Ihres Codes, der mit AWS-Services interagiert. In diesem Thema wird beschrieben, wie Sie mit `StaticReplayClient` dem einen gefälschten HTTP-Client erstellen, der anstelle des standardmäßigen HTTP-Clients verwendet werden kann, der normalerweise von AWS-Services verwendet wird. Dieser Client gibt die von Ihnen angegebenen HTTP-Antworten zurück, anstatt mit dem Dienst über das Netzwerk zu kommunizieren, sodass Tests bekannte Daten für Testzwecke abrufen.

Die `aws-smithy-http-client` Kiste enthält eine Testdienstprogrammklasse namens [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). Diese HTTP-Client-Klasse kann anstelle des Standard-HTTP-Clients angegeben werden, wenn ein AWS-Service Objekt erstellt wird.

Bei der `StaticReplayClient` Initialisierung von geben Sie eine Liste von HTTP-Anforderungs- und Antwortpaaren als `ReplayEvent` Objekte an. Während der Test ausgeführt wird, wird jede HTTP-Anfrage aufgezeichnet und der Client gibt die nächste HTTP-Antwort, die in der nächsten in der Ereignisliste gefunden wurde, als Antwort des HTTP-Clients zurück. `ReplayEvent` Dadurch kann der Test mit bekannten Daten und ohne Netzwerkverbindung ausgeführt werden.

## Statische Wiedergabe wird verwendet
<a name="testing-replay-steps"></a>

Um Static Replay zu verwenden, müssen Sie keinen Wrapper verwenden. Ermitteln Sie stattdessen, wie der tatsächliche Netzwerkverkehr für die Daten aussehen sollte, die Ihr Test verwenden wird, und stellen Sie diese Verkehrsdaten zur Verfügung, damit sie sie jedes Mal verwenden können, wenn das SDK eine Anfrage vom Client ausgibt. `StaticReplayClient` AWS-Service 

**Anmerkung**  
Es gibt mehrere Möglichkeiten, den erwarteten Netzwerkverkehr zu erfassen, darunter die AWS CLI und viele Tools zur Analyse des Netzwerkverkehrs und Paket-Sniffer-Tools.
+ Erstellen Sie eine Liste von `ReplayEvent` Objekten, die die erwarteten HTTP-Anfragen und die Antworten angeben, die für sie zurückgegeben werden sollen.
+ Erstellen Sie eine `StaticReplayClient` mithilfe der im vorherigen Schritt erstellten HTTP-Transaktionsliste.
+ Erstellen Sie ein Konfigurationsobjekt für den AWS Client und geben Sie das `StaticReplayClient` als das `Config` Objekt an`http_client`.
+ Erstellen Sie das AWS-Service Client-Objekt mithilfe der im vorherigen Schritt erstellten Konfiguration.
+ Führen Sie die Operationen, die Sie testen möchten, mit dem Serviceobjekt aus, das für die Verwendung von konfiguriert ist`StaticReplayClient`. Jedes Mal, wenn das SDK eine API-Anfrage an sendet AWS, wird die nächste Antwort in der Liste verwendet.
**Anmerkung**  
Die nächste Antwort in der Liste wird immer zurückgegeben, auch wenn die gesendete Anfrage nicht mit der Antwort im `ReplayEvent` Objektvektor übereinstimmt.
+ Wenn alle gewünschten Anfragen gestellt wurden, rufen Sie die `StaticReplayClient.assert_requests_match()` Funktion auf, um zu überprüfen, ob die vom SDK gesendeten Anfragen mit denen in der `ReplayEvent` Objektliste übereinstimmen.

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

Schauen wir uns die Tests für dieselbe `determine_prefix_file_size()` Funktion im vorherigen Beispiel an, verwenden aber Static Replay statt Mocking.

1. Fügen Sie in einer Befehlszeile für Ihr Projektverzeichnis die [https://crates.io/crates/aws-smithy-http-client](https://crates.io/crates/aws-smithy-http-client)Crate als Abhängigkeit hinzu:

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

   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 in Ihr Testcode-Modul beide Typen ein, die Sie benötigen.

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

1. Der Test beginnt mit der Erstellung der `ReplayEvent` Strukturen, die jede der HTTP-Transaktionen darstellen, die während des Tests stattfinden sollen. Jedes Ereignis enthält ein HTTP-Anforderungsobjekt und ein HTTP-Antwortobjekt, die die Informationen darstellen, mit denen AWS-Service sie normalerweise antworten würden. Diese Ereignisse werden an einen Aufruf übergeben an`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]);
   ```

   Das Ergebnis wird gespeichert in`replay_client`. Dies stellt einen HTTP-Client dar, der dann vom SDK für Rust verwendet werden kann, indem er in der Konfiguration des Clients angegeben wird.

1. Um den Amazon S3 S3-Client zu erstellen, rufen Sie die `from_conf()` Funktion der Client-Klasse auf, um den Client mithilfe eines Konfigurationsobjekts zu erstellen:

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

   Das Konfigurationsobjekt wird mit der `http_client()` Methode des Builders angegeben, und die Anmeldeinformationen werden mit der `credentials_provider()` Methode angegeben. Die Anmeldeinformationen werden mithilfe einer aufgerufenen Funktion erstellt`make_s3_test_credentials()`, die eine falsche Struktur der Anmeldeinformationen zurückgibt:

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

   Diese Anmeldeinformationen müssen nicht gültig sein, da sie nicht wirklich gesendet werden AWS.

1. Führen Sie den Test aus, indem Sie die Funktion aufrufen, die getestet werden muss. In diesem Beispiel lautet der Name dieser Funktion`determine_prefix_file_size()`. Sein erster Parameter ist das Amazon S3 S3-Client-Objekt, das für seine Anfragen verwendet werden soll. Geben Sie daher den Client an, der mit dem `StaticReplayClient` so erstellt wurde, dass Anfragen von diesem bearbeitet werden, anstatt über das Netzwerk gesendet zu werden:

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

   Wenn der Aufruf von abgeschlossen `determine_prefix_file_size()` ist, wird eine Bestätigung verwendet, um zu bestätigen, dass der zurückgegebene Wert dem erwarteten Wert entspricht. Dann wird die `StaticReplayClient` `assert_requests_match()` Methodenfunktion aufgerufen. Diese Funktion scannt die aufgezeichneten HTTP-Anfragen und bestätigt, dass sie alle mit denen übereinstimmen, die im `ReplayEvent` Objektarray angegeben wurden, das bei der Erstellung des Replay-Clients bereitgestellt wurde.

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

# Unit-Tests mit `aws-smithy-mocks` im AWS SDK für Rust
<a name="testing-smithy-mocks"></a>

Das AWS SDK für Rust bietet mehrere Ansätze zum Testen Ihres Codes, der mit AWS-Services interagiert. In diesem Thema wird beschrieben, wie Sie die [https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/](https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/)Crate verwenden. Sie bietet eine einfache und dennoch leistungsstarke Möglichkeit, Antworten von AWS SDK-Clients zu Testzwecken nachzuahmen.

## -Übersicht
<a name="overview-smithy-mock"></a>

Wenn Sie Tests für Code schreiben, der Use verwendet AWS-Services, möchten Sie häufig vermeiden, tatsächliche Netzwerkaufrufe zu tätigen. Die `aws-smithy-mocks` Crate bietet eine Lösung, indem sie Ihnen Folgendes ermöglicht:
+ Erstellen Sie Scheinregeln, die definieren, wie das SDK auf bestimmte Anfragen reagieren soll.
+ Gibt verschiedene Arten von Antworten zurück (Erfolg, Fehler, HTTP-Antworten).
+ Ordnen Sie Anfragen anhand ihrer Eigenschaften zu.
+ Definieren Sie Antwortsequenzen zum Testen des Wiederholungsverhaltens.
+ Stellen Sie sicher, dass Ihre Regeln wie erwartet verwendet wurden.

## Die Abhängigkeit wird hinzugefügt
<a name="dependency-smithy-mock"></a>

Fügen Sie in einer Befehlszeile für Ihr Projektverzeichnis die [https://crates.io/crates/aws-smithy-mocks](https://crates.io/crates/aws-smithy-mocks)Crate als Abhängigkeit hinzu:

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

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.

Dieser Beispielcode verwendet auch Amazon Simple Storage Service als AWS-Service Beispiel und erfordert eine Funktion`test-util`.

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

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

## Grundlegende Verwendung
<a name="basic-smithy-mocks"></a>

 Hier ist ein einfaches Beispiel für die Verwendung `aws-smithy-mocks` zum Testen von Code, der mit Amazon Simple Storage Service (Amazon S3) interagiert:

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

## Scheinregeln erstellen
<a name="creating-rules-smithy-mocks"></a>

Regeln werden mithilfe des `mock!` Makros erstellt, das eine Client-Operation als Argument verwendet. Anschließend können Sie konfigurieren, wie sich die Regel verhalten soll. 

### Passende Anfragen
<a name="matching-requests-smithy-mocks"></a>

 Sie können Regeln spezifischer gestalten, indem Sie Eigenschaften auf Anfrage abgleichen:

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

### Verschiedene Antworttypen
<a name="diff-response-smithy-mocks"></a>

Sie können verschiedene Arten von Antworten zurückgeben:

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

## Verhalten bei Wiederholungsversuchen testen
<a name="testing-retry-behavior-smithy-mocks"></a>

Eine der leistungsstärksten Funktionen von `aws-smithy-mocks` ist die Fähigkeit, das Wiederholungsverhalten zu testen, indem Sequenzen von Antworten definiert werden:

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

## Regelmodi
<a name="rule-modes-smithy-mocks"></a>

Mithilfe von Regelmodi können Sie steuern, wie Regeln abgeglichen und angewendet werden:

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

## Beispiel: Testen des Wiederholungsverhaltens
<a name="example-retry-smithy-mocks"></a>

Hier ist ein vollständigeres Beispiel, das zeigt, wie das Verhalten bei Wiederholungen getestet wird:

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

## Beispiel: Verschiedene Antworten basierend auf Anforderungsparametern
<a name="example-request-param-smithy-mocks"></a>

Sie können auch Regeln erstellen, die auf der Grundlage von Anforderungsparametern unterschiedliche Antworten zurückgeben:

```
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 Practices
<a name="best-practices-smithy-mocks"></a>

Bei der Verwendung `aws-smithy-mocks` zum Testen:

1.  Spezifische Anfragen zuordnen: Verwenden Sie diese Option`match_requests()`, um sicherzustellen, dass Ihre Regeln nur für die beabsichtigten Anfragen gelten, insbesondere für`RuleMode:::MatchAny`.

1.  Überprüfen Sie die Regelverwendung: Stellen `rule.num_calls()` Sie sicher, dass Ihre Regeln tatsächlich verwendet wurden.

1.  Testen Sie die Fehlerbehandlung: Erstellen Sie Regeln, die Fehler zurückgeben, um zu testen, wie Ihr Code mit Fehlern umgeht.

1.  Testen Sie die Wiederholungslogik: Verwenden Sie Antwortsequenzen, um zu überprüfen, ob Ihr Code alle benutzerdefinierten Wiederholungsklassifikatoren oder anderes Wiederholungsverhalten korrekt behandelt.

1. Konzentrieren Sie sich auf Tests: Erstellen Sie separate Tests für verschiedene Szenarien, anstatt zu versuchen, alles in einem Test abzudecken.