

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# AWS SDK for Rust `aws-smithy-mocks` での を使用したユニットテスト
<a name="testing-smithy-mocks"></a>

 AWS SDK for Rust は、 とやり取りするコードをテストするための複数のアプローチを提供します AWS のサービス。このトピックでは、テスト目的で AWS SDK クライアントのレスポンスのモックを作成するため、シンプルで強力な方法を提供する [https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/](https://docs.rs/aws-smithy-mocks/latest/aws_smithy_mocks/) クレートを使用する方法について説明します。

## 概要:
<a name="overview-smithy-mock"></a>

が使用するコードのテストを記述する場合 AWS のサービス、多くの場合、実際のネットワーク呼び出しは避けてください。`aws-smithy-mocks` クレートを使用すると、以下を実現するソリューションを提供します。
+ SDK が特定のリクエストにどのように応答するかを定義するモックルールを作成する。
+ さまざまなタイプのレスポンス (成功、エラー、HTTP レスポンス) を返す。
+ プロパティに基づいてリクエストを一致させる。
+ 再試行動作をテストするための応答のシーケンスを定義する。
+ ルールが想定どおりに使用されたことを確認する。

## 依存関係の追加
<a name="dependency-smithy-mock"></a>

プロジェクトディレクトリのコマンドプロンプトで、[https://crates.io/crates/aws-smithy-mocks](https://crates.io/crates/aws-smithy-mocks) クレートを次の依存関係として追加します。

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

`--dev` [オプション](https://doc.rust-lang.org/cargo/commands/cargo-add.html)を使用すると、`Cargo.toml` ファイルの `[dev-dependencies]` セクションにクレートが追加されます。[開発の依存関係](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies)として扱われるため、これはコンパイルされず、本番コードで使用される最終バイナリには含まれません。

このコード例では、Amazon Simple Storage Service も例として使用されており AWS のサービス、機能 が必要です`test-util`。

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

これにより、`[dependencies]` ファイルの `Cargo.toml` セクションにクレートが追加されます。

## 基本的な使用法
<a name="basic-smithy-mocks"></a>

 `aws-smithy-mocks` を使用して 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);
}
```

## モックルールの作成
<a name="creating-rules-smithy-mocks"></a>

ルールは、`mock!` マクロを使用して作成されます。マクロは、クライアントオペレーションを引数として受け取ります。その後、ルールがどのように動作するかを設定できます。

### リクエストの一致
<a name="matching-requests-smithy-mocks"></a>

 リクエストのプロパティを一致させることにより、ルールをより具体化できます。

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

### さまざまなレスポンスタイプ
<a name="diff-response-smithy-mocks"></a>

さまざまなタイプのレスポンスを返すことができます。

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

## 再試行動作のテスト
<a name="testing-retry-behavior-smithy-mocks"></a>

`aws-smithy-mocks` の最も強力な機能の 1 つは、レスポンスのシーケンスを定義して再試行動作をテストできることです。

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

## ルールモード
<a name="rule-modes-smithy-mocks"></a>

ルールモードを使用して、ルールの一致と適用方法を以下のように制御できます。

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

## 例: 再試行動作のテスト
<a name="example-retry-smithy-mocks"></a>

再試行動作をテストする方法を示す、より完全な例を以下に示します。

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

## 例: リクエストパラメータに基づくさまざまなレスポンス
<a name="example-request-param-smithy-mocks"></a>

リクエストパラメータに基づいて、異なるレスポンスを返すルールを作成することもできます。

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

## ベストプラクティス
<a name="best-practices-smithy-mocks"></a>

テストに `aws-smithy-mocks` を使用する場合:

1.  特定のリクエストに一致: `match_requests()` を使用して、ルールが意図したリクエスト (特に `RuleMode:::MatchAny`) にのみ適用されるようにします。

1.  ルールの使用状況を確認: `rule.num_calls()` を確認し、ルールが実際に使用されたことを確認します。

1.  テストエラー処理: エラーを返すルールを作成して、コードによって失敗を処理する方法をテストします。

1.  テスト再試行ロジック: レスポンスシーケンスを使用して、コードによってカスタム再試行分類子やその他の再試行動作を正しく処理することを確認します。

1. テストに集中: 1 つのテストですべてを網羅しようとするのではなく、シナリオごとに個別のテストを作成します。