

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.

# Verwenden Sie das SDK
<a name="using"></a>

Dieser Abschnitt enthält grundlegende Informationen, die für die Verwendung von erforderlich sind AWS SDK für Kotlin.

**Topics**
+ [

# Anfragen stellen
](making-requests.md)
+ [

# Coroutinen
](coroutines.md)
+ [

# Streaming-Operationen
](streaming-ops.md)
+ [

# Paginierung
](pagination.md)
+ [

# Waiter
](waiters.md)
+ [

# Fehlerbehandlung
](error-handling.md)
+ [

# Anfragen vorab signieren
](presign-requests.md)
+ [

# Problembehebung FAQs
](troubleshooting-faqs.md)
+ [

# Spott in der AWS SDK für Kotlin
](mocking.md)

# Anfragen stellen
<a name="making-requests"></a>

Verwenden Sie einen Service-Client, um Anfragen an einen zu stellen AWS-Service. Der AWS SDK für Kotlin stellt domänenspezifische Sprachen (DSLs) zur Verfügung, die einem [typsicheren Builder-Muster](https://kotlinlang.org/docs/type-safe-builders.html) folgen, um Anfragen zu erstellen. Auf verschachtelte Strukturen von Anfragen kann auch über sie zugegriffen werden. DSLs

Das folgende Beispiel zeigt, wie Sie eine Amazon DynamoDB [CreateTable-Operationseingabe erstellen](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/dynamodb/aws.sdk.kotlin.services.dynamodb/create-table.html):

```
val ddb = DynamoDbClient.fromEnvironment()

val req = CreateTableRequest {
    tableName = name
    keySchema = listOf(
        KeySchemaElement {
            attributeName = "year"
            keyType = KeyType.Hash
        },
        KeySchemaElement {
            attributeName = "title"
            keyType = KeyType.Range
        }
    )

    attributeDefinitions = listOf(
        AttributeDefinition {
            attributeName = "year"
            attributeType = ScalarAttributeType.N
        },
        AttributeDefinition {
            attributeName = "title"
            attributeType = ScalarAttributeType.S
        }
    )
    
    // You can configure the `provisionedThroughput` member
    // by using the `ProvisionedThroughput.Builder` directly:
    provisionedThroughput {
        readCapacityUnits = 10
        writeCapacityUnits = 10
    }
}

val resp = ddb.createTable(req)
```

## DSL-Überladungen der Serviceschnittstelle
<a name="service-interface-dsl-overloads"></a>

Jeder Nicht-Streaming-Vorgang auf der Service-Client-Schnittstelle weist eine DSL-Überlastung auf, sodass Sie keine separate Anforderung erstellen müssen.

Beispiel für die Erstellung eines Amazon Simple Storage Service (Amazon S3) -Buckets mit der überladenen Funktion:

```
s3Client.createBucket {    // this: CreateBucketRequest.Builder
    bucket = newBucketName
}
```

Dies entspricht:

```
val request = CreateBucketRequest {    // this: CreateBucketRequest.Builder 
    bucket = newBucketName 
}

s3client.createBucket(request)
```

## Anfragen ohne erforderliche Eingaben
<a name="requests-no-required-inputs"></a>

Operationen, für die keine erforderlichen Eingaben erforderlich sind, können aufgerufen werden, ohne dass ein Anforderungsobjekt übergeben werden muss. Dies ist häufig bei Operationen vom Typ Liste möglich, z. B. bei der Amazon `listBuckets` S3-API-Operation.

 Die folgenden drei Anweisungen sind beispielsweise gleichwertig: 

```
s3Client.listBuckets(ListBucketsRequest {
  // Construct the request object directly.
})
s3Client.listBuckets {
  // DSL builder without explicitly setting any arguments.
}
s3Client.listBuckets()
```

# Coroutinen
<a name="coroutines"></a>

Der AWS SDK für Kotlin ist standardmäßig asynchron. Das SDK für Kotlin verwendet `suspend` Funktionen für alle Operationen, die dazu bestimmt sind, von einer Coroutine aus aufgerufen zu werden. 

[Eine ausführlichere Anleitung zu Coroutinen finden Sie in der offiziellen Kotlin-Dokumentation.](https://kotlinlang.org/docs/coroutines-overview.html)

## Gleichzeitige Anfragen stellen
<a name="making-concurrent-requests"></a>

Der [asynchrone](https://kotlinlang.org/docs/composing-suspending-functions.html#concurrent-using-async) Coroutine Builder kann verwendet werden, um gleichzeitige Anfragen zu starten, bei denen Ihnen die Ergebnisse wichtig sind. `async`gibt einen Wert vom Typ [Deferred](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html) zurück, was für eine leichtgewichtige, nicht blockierende future steht, die ein Versprechen darstellt, zu einem späteren Zeitpunkt ein Ergebnis zu liefern.

[Wenn Ihnen die Ergebnisse egal sind (nur, dass ein Vorgang abgeschlossen wurde), können Sie den Launch Coroutine Builder verwenden.](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html) `launch`ist konzeptionell ähnlich wie. `async` Der Unterschied besteht darin, dass launch einen [Job](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html) zurückgibt und keinen Ergebniswert enthält, während launch a `async` zurückgibt`Deferred`.

Im Folgenden finden Sie ein Beispiel für gleichzeitige Anfragen an Amazon S3 mithilfe der Operation [headObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/head-object.html), um die Inhaltsgröße von zwei Schlüsseln abzurufen:

```
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis
import aws.sdk.kotlin.services.s3.S3Client


fun main(): Unit = runBlocking {

    val s3 = S3Client { region = "us-east-2" }
    
    val myBucket = "<your-bucket-name-here>"
    val key1 = "<your-object-key-here>"
    val key2 = "<your-second-object-key-here>"

    val resp1 = async {
        s3.headObject{
            bucket = myBucket
            key = key1
        }
    }

    val resp2 = async {
        s3.headObject{
            bucket = myBucket
            key = key2
        }
    }


    val elapsed = measureTimeMillis {
        val totalContentSize = resp1.await().contentLength + resp2.await().contentLength
        println("content length of $key1 + $key2 = $totalContentSize")
    }

    println("requests completed in $elapsed ms")

}
```

## Blockierungsanfragen stellen
<a name="making-clocking-requests"></a>

Um Serviceaufrufe von vorhandenem Code aus zu tätigen, der keine Coroutinen verwendet und ein anderes Threading-Modell implementiert, können Sie den [RunBlocking-Coroutine-Builder](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) verwenden. Ein Beispiel für ein anderes Threading-Modell ist die Verwendung des traditionellen Ansatzes von Java. executors/futures Möglicherweise müssen Sie diesen Ansatz verwenden, wenn Sie Java- und Kotlin-Code oder -Bibliotheken mischen. 

Wie der Name schon sagt, startet dieser `runBlocking` Builder eine neue Coroutine und blockiert den aktuellen Thread, bis er abgeschlossen ist. 

**Warnung**  
 `runBlocking`sollte im Allgemeinen nicht von einer Coroutine aus verwendet werden. Es wurde entwickelt, um regulären Blockierungscode mit Bibliotheken zu verbinden, die im Suspending-Stil geschrieben sind (z. B. in Hauptfunktionen und Tests). 

# Streaming-Operationen
<a name="streaming-ops"></a>

In der AWS SDK für Kotlin werden Binärdaten (Streams) als [https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.content/-byte-stream/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.content/-byte-stream/index.html)Typ dargestellt, bei dem es sich um einen abstrakten, schreibgeschützten Bytestrom handelt.

## Streaming-Antworten
<a name="streaming-responses"></a>

Antworten mit einem binären Stream (z. B. der [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)API-Vorgang Amazon Simple Storage Service (Amazon S3)) werden anders behandelt als andere Methoden. Diese Methoden verwenden eine Lambda-Funktion, die die Antwort verarbeitet, anstatt die Antwort direkt zurückzugeben. Dadurch wird der Umfang der Antwort auf die Funktion beschränkt und die Lebenszeitverwaltung sowohl für den Aufrufer als auch für die SDK-Laufzeit vereinfacht.

Nach der Rückkehr der Lambda-Funktion werden alle Ressourcen wie die zugrunde liegende HTTP-Verbindung freigegeben. (Auf sie `ByteStream` sollte nicht zugegriffen werden, nachdem das Lambda zurückgekehrt ist, und sie sollten auch nicht nach der Schließung weitergegeben werden.) Das Ergebnis des Aufrufs ist das, was das Lambda zurückgibt.

Das folgende Codebeispiel zeigt, wie die Funktion [GetObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/-s3-client/get-object.html) einen Lambda-Parameter empfängt, der die Antwort verarbeitet.

```
val s3Client = S3Client.fromEnvironment()
val req = GetObjectRequest { ... }

val path = Paths.get("/tmp/download.txt")

// S3Client.getObject has the following signature:
// suspend fun <T> getObject(input: GetObjectRequest, block: suspend (GetObjectResponse) -> T): T

val contentSize = s3Client.getObject(req) { resp ->
    // resp is valid until the end of the block.
    // Do not attempt to store or process the stream after the block returns.
    
    // resp.body is of type ByteStream.
    val rc = resp.body?.writeToFile(path)
    rc
}
println("wrote $contentSize bytes to $path")
```

Der `ByteStream` Typ hat die folgenden Erweiterungen für gängige Verwendungsarten:
+ `ByteStream.writeToFile(file: File): Long`
+ `ByteStream.writeToFile(path: Path): Long`
+ `ByteStream.toByteArray(): ByteArray`
+ `ByteStream.decodeToString(): String`

All dies ist im `aws.smithy.kotlin.runtime.content` Paket definiert.

## Streaming-Anfragen
<a name="streaming-requests"></a>

Um eine bereitzustellen`ByteStream`, gibt es auch mehrere praktische Methoden, darunter die folgenden:
+ `ByteStream.fromFile(file: File)`
+ `File.asByteStream(): ByteStream`
+ `Path.asByteStream(): ByteStream`
+ `ByteStream.fromBytes(bytes: ByteArray)`
+ `ByteStream.fromString(str: String)`

All dies ist im `aws.smithy.kotlin.runtime.content` Paket definiert.

Das folgende Codebeispiel zeigt die Verwendung `ByteStream` praktischer Methoden, die die Eigenschaft body bei der Erstellung eines bereitstellen [PutObjectRequest](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.model/-put-object-request/index.html):

```
val req = PutObjectRequest {
    ...
    body = ByteStream.fromFile(file)
    // body = ByteStream.fromBytes(byteArray)
    // body = ByteStream.fromString("string")
    // etc
}
```

# Paginierung
<a name="pagination"></a>

Viele AWS Operationen geben paginierte Ergebnisse zurück, wenn die Nutzlast zu groß ist, um sie in einer einzigen Antwort zurückzugeben. AWS SDK für Kotlin Dazu gehören [Erweiterungen](https://kotlinlang.org/docs/extensions.html) der Service-Client-Schnittstelle, die die Ergebnisse auto für Sie paginieren. Sie müssen nur den Code schreiben, der die Ergebnisse verarbeitet.

Die Paginierung wird als [Flow bereitgestellt](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)<T>, sodass Sie die idiomatischen Transformationen von Kotlin für asynchrone Sammlungen (wie`map`, und) nutzen können. `filter` `take` Ausnahmen sind transparent, sodass sich die Fehlerbehandlung wie ein regulärer API-Aufruf anfühlt, und die Stornierung entspricht der allgemeinen kooperativen Annullierung von Coroutinen. Weitere Informationen finden Sie im offiziellen [Leitfaden unter Abläufe](https://kotlinlang.org/docs/flow.html) und [Flow-Ausnahmen](https://kotlinlang.org/docs/flow.html#flow-exceptions).

**Anmerkung**  
In den folgenden Beispielen wird Amazon S3 verwendet. Die Konzepte sind jedoch für jeden Service identisch, der über einen oder mehrere Seiten verfügt. APIs Alle Paginierungserweiterungen sind im `aws.sdk.kotlin.services.<service>.paginators` Paket definiert (z. B.`aws.sdk.kotlin.services.dynamodb.paginators`). 

Das folgende Codebeispiel zeigt, wie Sie die paginierte Antwort aus dem Funktionsaufruf [ListObjectsV2Paginated](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.paginators/list-objects-v2-paginated.html) verarbeiten können. 

**Importe**

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.paginators.listObjectsV2Paginated
import kotlinx.coroutines.flow.*
```

**Code**

```
val s3 = S3Client.fromEnvironment()
val req = ListObjectsV2Request {
    bucket = "amzn-s3-demo-bucket"
    maxKeys = 1
}

s3.listObjectsV2Paginated(req)  // Flow<ListObjectsV2Response>
    .transform { it.contents?.forEach { obj -> emit(obj) } }
    .collect { obj ->
        println("key: ${obj.key}; size: ${obj.size}")
    }
```

# Waiter
<a name="waiters"></a>

Waiter sind eine clientseitige Abstraktion, die verwendet wird, um eine Ressource abzufragen, bis ein gewünschter Status erreicht ist oder bis festgestellt wird, dass die Ressource nicht in den gewünschten Zustand übergeht. Dies ist eine häufige Aufgabe, wenn Sie mit Diensten arbeiten, die irgendwann konsistent sind, wie Amazon Simple Storage Service (Amazon S3), oder mit Diensten, die asynchron Ressourcen erstellen, wie Amazon EC2. 

Das Schreiben von Logik zur kontinuierlichen Abfrage des Status einer Ressource kann umständlich und fehleranfällig sein. Das Ziel der Kellner ist es, diese Verantwortung aus dem Kundencode in den Kundencode zu verlagern AWS SDK für Kotlin, der über fundierte Kenntnisse der zeitlichen Abläufe verfügt. AWS 

**Anmerkung**  
In den folgenden Beispielen wird Amazon S3 verwendet. Die Konzepte sind jedoch für alle AWS-Service , für die ein oder mehrere Kellner definiert sind, dieselben. Alle Erweiterungen sind im `aws.sdk.kotlin.services.<service>.waiters` Paket definiert (z. B.`aws.sdk.kotlin.services.dynamodb.waiters`). Sie folgen außerdem einer Standardbenennungskonvention (`waitUntil<Condition>`).

Das folgende Codebeispiel zeigt die Verwendung einer Kellnerfunktion, mit der Sie das Schreiben von Abfragelogik vermeiden können.

**Importe**

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.waiters.waitUntilBucketExists
```

**Code**

```
val s3 = S3Client.fromEnvironment()

// This initiates creating an S3 bucket and potentially returns before the bucket exists.
s3.createBucket { bucket = "amzn-s3-demo-bucket" }

// When this function returns, the bucket either exists or an exception
// is thrown.
s3.waitUntilBucketExists { bucket = "amzn-s3-demo-bucket" }

// The bucket now exists.
```

**Anmerkung**  
Jede Wartemethode gibt eine `Outcome` Instanz zurück, die verwendet werden kann, um die endgültige Antwort zu erhalten, die dem Erreichen der gewünschten Bedingung entspricht. Ein Ergebnis enthält auch zusätzliche Details wie die Anzahl der Versuche, den gewünschten Status zu erreichen.

# Fehlerbehandlung
<a name="error-handling"></a>

Es ist wichtig zu verstehen, wie AWS SDK für Kotlin und wann Ausnahmen ausgelöst werden, um qualitativ hochwertige Anwendungen mithilfe des SDK zu erstellen. In den folgenden Abschnitten werden die verschiedenen Fälle von Ausnahmen beschrieben, die vom SDK ausgelöst werden, und wie sie korrekt verarbeitet werden.

## Ausnahmen für Dienste
<a name="service-exceptions"></a>

Die häufigste Ausnahme ist die`AwsServiceException`, von der alle dienstspezifischen Ausnahmen (wie`S3Exception`) erben. Diese Ausnahme stellt eine Fehlerantwort von einem dar. AWS-Service Wenn Sie beispielsweise versuchen, eine EC2 Amazon-Instance zu beenden, die nicht existiert, gibt Amazon eine Fehlerantwort EC2 zurück. Die Details zur Fehlerantwort sind in der Datei enthalten`AwsServiceException`, die ausgelöst wird. 

Wenn Sie auf eine stoßen`AwsServiceException`, bedeutet dies, dass Ihre Anfrage erfolgreich an die gesendet wurde, AWS-Service aber nicht bearbeitet werden konnte. Dies kann an Fehlern in den Parametern der Anforderung oder an Problemen auf Seiten des Services liegen.

## Ausnahmen für Kunden
<a name="client-exceptions"></a>

`ClientException`weist darauf hin, dass im AWS SDK für Kotlin Client-Code ein Problem aufgetreten ist, entweder beim Versuch, eine Anfrage an zu senden, AWS oder beim Versuch, eine Antwort von AWS zu analysieren. A `ClientException` ist im Allgemeinen schwerwiegender als ein `AwsServiceException` und weist darauf hin, dass ein schwerwiegendes Problem darin besteht, den Client daran zu hindern, Serviceanrufe an zu AWS-Services verarbeiten. Beispielsweise gibt der Befehl AWS SDK für Kotlin a aus, `ClientException` wenn er eine Antwort von einem Dienst nicht analysieren kann.

## Fehler-Metadaten
<a name="error-metadata"></a>

Jede Service- und Client-Ausnahme hat die `sdkErrorMetadata` Eigenschaft. Dies ist ein typisierter Eigenschaften-Bag, der verwendet werden kann, um zusätzliche Informationen zu dem Fehler abzurufen.

Für den `AwsErrorMetadata` Typ existieren direkt mehrere vordefinierte Erweiterungen, einschließlich, aber nicht beschränkt auf die folgenden:
+ `sdkErrorMetadata.requestId`— die eindeutige Anfrage-ID
+ `sdkErrorMetadata.errorMessage`— die für Menschen lesbare Nachricht (entspricht normalerweise der`Exception.message`, kann aber mehr Informationen enthalten, wenn die Ausnahme dem Dienst unbekannt war)
+ `sdkErrorMetadata.protocolResponse`— Die rohe Protokollantwort

Das folgende Beispiel zeigt den Zugriff auf die Fehlermetadaten.

```
try {
    s3Client.listBuckets { ... }
} catch (ex: S3Exception) {
    val awsRequestId = ex.sdkErrorMetadata.requestId
    val httpResp = ex.sdkErrorMetadata.protocolResponse as? HttpResponse

    println("requestId was: $awsRequestId")
    println("http status code was: ${httpResp?.status}")
}
```

# Anfragen vorab signieren
<a name="presign-requests"></a>

Sie können Anfragen für einige AWS API-Operationen vorab signieren, sodass ein anderer Aufrufer die Anfrage später verwenden kann, ohne seine eigenen Anmeldeinformationen angeben zu müssen. 

Nehmen wir zum Beispiel an, dass Alice Zugriff auf ein Amazon Simple Storage Service (Amazon S3) -Objekt hat und den Objektzugriff vorübergehend mit Bob teilen möchte. Alice kann eine vorab signierte `GetObject` Anfrage zur Weitergabe an Bob generieren, sodass er das Objekt herunterladen kann, ohne Zugriff auf Alices Anmeldeinformationen zu benötigen.

## Grundlagen der Vorsignierung
<a name="presign-requests-basics"></a>

Das SDK für Kotlin bietet Erweiterungsmethoden für Service-Clients zur Vorsignierung von Anfragen. Alle vorsignierten Anfragen benötigen eine Dauer, die angibt, wie lange die signierte Anfrage gültig ist. Nach Ablauf der Dauer läuft die vorsignierte Anforderung ab und löst einen Authentifizierungsfehler aus, wenn sie ausgeführt wird.

Der folgende Code zeigt ein Beispiel, das eine vorsignierte `GetObject` Anfrage für Amazon S3 erstellt. Die Anfrage ist nach ihrer Erstellung 24 Stunden lang gültig.

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = GetObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignGetObject(unsignedRequest, 24.hours)
```

Die [https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html)Erweiterungsmethode gibt ein [https://docs.aws.amazon.com/smithy-kotlin/api/latest/http/aws.smithy.kotlin.runtime.http.request/-http-request/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http/aws.smithy.kotlin.runtime.http.request/-http-request/index.html)Objekt zurück. Das Anforderungsobjekt enthält die vorsignierte URL, über die die Operation aufgerufen werden kann. Ein anderer Aufrufer kann die URL (oder die gesamte Anfrage) in einer anderen Codebasis- oder Programmiersprachenumgebung verwenden.

Nachdem Sie die vorsignierte Anfrage erstellt haben, verwenden Sie einen HTTP-Client, um eine Anfrage aufzurufen. Die API zum Aufrufen einer HTTP-GET-Anfrage hängt vom HTTP-Client ab. Das folgende Beispiel verwendet die Kotlin-Methode [https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.net.-u-r-l/read-text.html](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.net.-u-r-l/read-text.html).

```
val objectContents = URL(presignedRequest.url.toString()).readText()
println(objectContents)
```

## Erweiterte Presigning-Konfiguration
<a name="presign-requests-conf-advanced"></a>

Im SDK verfügt jede Methode, mit der Anfragen vorab signiert werden können, über eine Vielzahl von Funktionen, die Sie verwenden können, um erweiterte Konfigurationsoptionen bereitzustellen, z. B. eine spezifische Implementierung für den Unterzeichner oder detaillierte Signaturparameter.

Das folgende Beispiel zeigt eine Amazon S3 `GetObject` S3-Anfrage, die die CRT-Signaturvariante verwendet und ein future Signaturdatum angibt.

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = GetObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignGetObject(unsignedRequest, signer = CrtAwsSigner) {
    signingDate = Instant.now() + 24.hours
    expiresAfter = 8.hours
}
```

Die zurückgesandte, vorsignierte Anfrage ist 24 Stunden im Voraus gültig und bis dahin nicht gültig. Danach läuft sie 8 Stunden ab.

## Vorsignierung von POST- und PUT-Anfragen
<a name="presign-requests-post-put"></a>

Viele Operationen, die vorsignierbar sind, benötigen nur eine URL und müssen als HTTP-GET-Anfragen ausgeführt werden. Einige Operationen benötigen jedoch einen Hauptteil und müssen in einigen Fällen als HTTP-POST-Anforderung oder HTTP-PUT-Anfrage zusammen mit Headern ausgeführt werden. Das Vorsignieren dieser Anfragen ist identisch mit dem Vorsignieren von GET-Anfragen, das Aufrufen der vorab signierten Anforderung ist jedoch komplizierter.

Hier ist ein Beispiel für die Vorsignierung einer S3-Anfrage: `PutObject`

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = PutObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignPutObject(unsignedRequest, 24.hours)
```

Die zurückgegebene Datei `HttpRequest` hat einen Methodenwert von `HttpMethod.PUT` und enthält eine URL und Header, die beim future Aufruf der HTTP-Anfrage enthalten sein müssen. Sie können diese Anforderung an einen Aufrufer weiterleiten, der sie in einer anderen Codebasis- oder Programmiersprachenumgebung ausführen kann.

Nachdem Sie die vorsignierte POST- oder PUT-Anforderung erstellt haben, verwenden Sie einen HTTP-Client, um eine Anfrage aufzurufen. Die API zum Aufrufen einer POST- oder PUT-Anforderungs-URL hängt vom verwendeten HTTP-Client ab. Das folgende Beispiel verwendet einen [OkHttp HTTP-Client](https://square.github.io/okhttp) und enthält einen Hauptteil, der Folgendes enthält`Hello world`.

```
val putRequest = Request
    .Builder()
    .url(presignedRequest.url.toString())
    .apply {
        presignedRequest.headers.forEach { key, values ->
            header(key, values.joinToString(", "))
        }
    }
    .put("Hello world".toRequestBody())
    .build()

val response = okHttp.newCall(putRequest).execute()
```

## Operationen, die das SDK vorab signieren kann
<a name="presign-ops-supported"></a>

Das SDK für Kotlin unterstützt derzeit die Vorsignierung der folgenden API-Operationen, die mit der zugehörigen HTTP-Methode aufgerufen werden müssen.


| AWS-Service | Operation | SDK-Erweiterungsmethode | Verwenden Sie die HTTP-Methode | 
| --- | --- | --- | --- | 
| Amazon S3 | GetObject | [presignGetObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html) |  HTTP GET  | 
| Amazon S3 | PutObject | [presignPutObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-put-object.html) |  HTTP EINGEBEN  | 
| Amazon S3 | UploadPart |  [presignUploadPart](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-upload-part.html)  |  HTTP SETZEN  | 
| AWS -Security-Token-Service | GetCallerIdentity |  [presignGetCallerIdentität](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/sts/aws.sdk.kotlin.services.sts.presigners/presign-get-caller-identity.html)  |  HTTP-BEITRAG  | 
| Amazon Polly | SynthesizeSpeech |  [presignSynthesizeSpeech](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/polly/aws.sdk.kotlin.services.polly.presigners/presign-synthesize-speech.html)  |  HTTP-BEITRAG  | 

# Problembehebung FAQs
<a name="troubleshooting-faqs"></a>

 AWS SDK für Kotlin Bei der Verwendung von in Ihren Anwendungen können einige der in diesem Thema aufgeführten Probleme auftreten. Verwenden Sie die folgenden Vorschläge, um die Ursache zu ermitteln und den Fehler zu beheben.

## Wie behebe ich Probleme mit dem Hinweis „Verbindung geschlossen“?
<a name="ts-faq-connection-closed"></a>

Möglicherweise treten in Ausnahmefällen Probleme mit dem Hinweis „Verbindung geschlossen“ auf, z. B. eines der folgenden Typen: 
+ `IOException: unexpected end of stream on <URL>`
+ `EOFException: \n not found: limit=0`
+ `HttpException: AWS_ERROR_HTTP_CONNECTION_CLOSED: The connection has closed or is closing.; crtErrorCode=2058; HttpErrorCode(CONNECTION_CLOSED)`

Diese Ausnahmen weisen darauf hin, dass eine TCP-Verbindung vom SDK zu einem Dienst unerwartet geschlossen oder zurückgesetzt wurde. Die Verbindung wurde möglicherweise von Ihrem Host, dem AWS Dienst oder einer zwischengeschalteten Partei wie einem NAT-Gateway, einem Proxy oder einem Load Balancer geschlossen.

Diese Arten von Ausnahmen werden automatisch wiederholt, können aber je nach Ihrer Protokollierungskonfiguration immer noch in SDK-Protokollen erscheinen. Wenn die Ausnahme in Ihrem Code ausgelöst wird, bedeutet dies, dass die aktive Wiederholungsstrategie ihre konfigurierten Grenzwerte wie die maximale Anzahl der Versuche oder den Token-Bucket für Wiederholungen ausgeschöpft hat. Weitere Informationen zu Wiederholungsstrategien finden Sie im [Wiederholungen im AWS SDK für Kotlin](retries.md) Abschnitt dieses Handbuchs. Siehe auch [Warum werden Ausnahmen ausgelöst, bevor die maximale Anzahl an Versuchen erreicht ist?](#ts-faq-exceptions-before-max).

### Überwachung von Verbindungen im Leerlauf mit dem OkHttpEngine
<a name="ts-faq-connection-closed-okhttp"></a>

Wenn Sie die verwenden `OkHttpEngine` und häufig auf `IOException: unexpected end of stream on <URL>` Ausnahmen stoßen, [sollten Sie die Aktivierung der Überwachung inaktiver Verbindungen in Betracht ziehen](http-client-config.md#http-idle-connection-monitoring). Diese Funktion erkennt, wenn Remoteserver Verbindungen geschlossen haben, die sich noch im Verbindungspool befinden, wodurch das Auftreten dieser Ausnahmen reduziert werden kann.

## Warum werden Ausnahmen ausgelöst, bevor die maximale Anzahl an Versuchen erreicht ist?
<a name="ts-faq-exceptions-before-max"></a>

Manchmal werden Ausnahmen angezeigt, von denen Sie erwartet hatten, dass sie wiederholt werden, aber stattdessen ausgelöst wurden. In diesen Situationen können die folgenden Schritte helfen, das Problem zu lösen.
+ **Stellen Sie sicher, dass die Ausnahme erneut versucht werden kann.** Einige Ausnahmen können nicht erneut versucht werden, z. B. solche, die auf eine fehlerhafte Serviceanfrage, fehlende Berechtigungen und nicht vorhandene Ressourcen hinweisen. Das SDK wiederholt diese Art von Ausnahmen nicht automatisch. Informationen darüber, wie Sie nach Ausnahmen suchen, die wiederholt werden können, finden Sie unter. [Prüfen Sie, ob eine Ausnahme erneut versucht werden kann](retries.md#retries-check-exception-retryable)
+ **Vergewissern Sie sich, dass die Ausnahme in Ihren Code aufgenommen wird.** Einige Ausnahmen erscheinen in Protokollnachrichten als Information, werden aber nicht wirklich in Ihren Code aufgenommen. Beispielsweise können Ausnahmen, die wiederholt werden können, wie Drosselungsfehler, protokolliert werden, da das SDK automatisch mehrere Zyklen durchläuft. backoff-and-retry Der Aufruf eines SDK-Vorgangs löst nur dann eine Ausnahme aus, wenn er nicht durch die konfigurierten Wiederholungseinstellungen behandelt wurde.
+ **Überprüfen Sie Ihre konfigurierten Einstellungen für den erneuten Versuch.** Weitere Informationen zu Wiederholungsstrategien und Wiederholungsrichtlinien finden Sie im [Wiederholungen im AWS SDK für Kotlin](retries.md) Abschnitt dieses Handbuchs. Stellen Sie sicher, dass Ihr Code die von Ihnen erwarteten Einstellungen oder die automatischen Standardeinstellungen verwendet.
+ **Erwägen Sie, Ihre Einstellungen für den erneuten Versuch anzupassen.** Nachdem Sie die vorherigen Punkte überprüft haben, das Problem jedoch nicht behoben wurde, sollten Sie erwägen, die Einstellungen für den erneuten Versuch anzupassen.
  + **Erhöhen Sie die maximale Anzahl von Versuchen.** Standardmäßig beträgt die maximale Anzahl von Versuchen für einen Vorgang 3. Wenn Sie der Meinung sind, dass dies nicht ausreicht und bei der Standardeinstellung immer noch Ausnahmen auftreten, sollten Sie erwägen, die `retryStrategy.maxAttempts` Eigenschaft in Ihrer Client-Konfiguration zu erhöhen. Weitere Informationen finden Sie unter [Konfigurieren Sie die maximale Anzahl an Versuchen](retries.md#retires-max-attempts).
  + **Erhöhen Sie die Verzögerungseinstellungen.** Einige Ausnahmen werden möglicherweise zu schnell wiederholt, bevor die Grunderkrankung behoben werden konnte. Wenn Sie vermuten, dass dies der Fall ist, sollten Sie erwägen, die `retryStrategy.delayProvider.maxBackoff` Eigenschaften `retryStrategy.delayProvider.initialDelay` oder in Ihrer Client-Konfiguration zu erhöhen. Weitere Informationen finden Sie unter [Konfigurieren Sie Verzögerungen und Backoff](retries.md#retries-delays-backoff).
  + **Deaktivieren Sie den Schutzschaltermodus.** Das SDK verwaltet standardmäßig einen Token-Bucket für jeden Service-Client. Wenn das SDK versucht, eine Anfrage zu stellen und diese mit einer wiederholbaren Ausnahme fehlschlägt, wird die Token-Anzahl verringert. Wenn die Anfrage erfolgreich ist, wird die Token-Anzahl erhöht. 

    Wenn dieser Token-Bucket 0 verbleibende Token erreicht, ist die Verbindung standardmäßig unterbrochen. Nachdem die Verbindung unterbrochen wurde, deaktiviert das SDK Wiederholungsversuche, und alle aktuellen und nachfolgenden Anfragen, die beim ersten Versuch fehlschlagen, lösen sofort eine Ausnahme aus. Das SDK aktiviert Wiederholungsversuche erneut, nachdem erfolgreiche erste Versuche dem Token-Bucket genügend Kapazität zurückgegeben haben. Dieses Verhalten ist beabsichtigt und wurde entwickelt, um Wiederholungsversuche bei Serviceausfällen und bei Servicewiederherstellungen zu verhindern.

    Wenn Sie es vorziehen, dass das SDK die Wiederholungsversuche bis zur maximal konfigurierten Anzahl von Versuchen fortsetzt, sollten Sie den Circuit Breaker-Modus deaktivieren, indem Sie die `retryStrategy.tokenBucket.useCircuitBreakerMode` Eigenschaft in Ihrer Client-Konfiguration auf False setzen. Wenn diese Eigenschaft auf false gesetzt ist, wartet der SDK-Client, bis der Token-Bucket genügend Kapazität erreicht hat, anstatt weitere Versuche abzubrechen, die zu einer Ausnahme führen könnten, wenn 0 Token übrig sind.

## Wie behebe `NoSuchMethodError` ich oder? NoClassDefFoundError
<a name="ts-faq-nusuchmethod"></a>

Diese Fehler werden am häufigsten durch fehlende oder widersprüchliche Abhängigkeiten verursacht. Weitere Informationen finden Sie unter [Wie löse ich Abhängigkeitskonflikte?](ts-faq-dep-conflict-resolution.md).

### Ich sehe ein für `NoClassDefFoundError` `okhttp3/coroutines/ExecuteAsyncKt`
<a name="ts-faq-nusuchmethod-okhttp"></a>

Dies deutet OkHttp speziell auf ein Abhängigkeitsproblem hin. Weitere Informationen finden Sie unter [Lösung von OkHttp Versionskonflikten in Ihrer Anwendung](ts-faq-dep-conflict-resolution.md#okhttp-dep-conflicts).

# Wie löse ich Abhängigkeitskonflikte?
<a name="ts-faq-dep-conflict-resolution"></a>

Wenn Sie das verwenden AWS SDK für Kotlin, benötigt es bestimmte Abhängigkeiten AWS und Abhängigkeiten von Drittanbietern, damit es ordnungsgemäß funktioniert. Wenn diese Abhängigkeiten fehlen oder zur Laufzeit unerwartete Versionen vorliegen, werden möglicherweise Fehler wie `NoSuchMethodError` oder angezeigt`NoClassDefFoundError`. Diese Abhängigkeitsprobleme lassen sich normalerweise in zwei Gruppen einteilen:
+ SDK/Smithy-Abhängigkeitskonflikte
+ Konflikte mit Abhängigkeiten von Drittanbietern

Wenn Sie Ihre Kotlin-Anwendung erstellen, werden Sie wahrscheinlich Gradle verwenden, um Abhängigkeiten zu verwalten. Das Hinzufügen einer Abhängigkeit von einem SDK-Serviceclient zu Ihrem Projekt beinhaltet automatisch alle erforderlichen zugehörigen Abhängigkeiten. Wenn Ihre Anwendung jedoch andere Abhängigkeiten hat, können diese mit den vom SDK geforderten Abhängigkeiten kollidieren. Das SDK stützt sich beispielsweise auf OkHttp einen beliebten HTTP-Client, den Ihre Anwendung möglicherweise auch verwendet. Um Ihnen zu helfen, diese Konflikte zu erkennen, bietet Gradle eine praktische Aufgabe, die die Abhängigkeiten Ihres Projekts auflistet:

```
./gradlew dependencies
```

Wenn Sie auf Abhängigkeitskonflikte stoßen, müssen Sie möglicherweise Maßnahmen ergreifen. Sie können entweder eine bestimmte Version einer Abhängigkeit angeben oder Abhängigkeiten in einen lokalen Namespace übertragen. Die Auflösung von Gradle-Abhängigkeiten ist ein komplexes Thema, das in den folgenden Abschnitten des *Gradle-Benutzerhandbuchs* behandelt wird:
+ [Die Auflösung von Abhängigkeiten verstehen](https://docs.gradle.org/current/userguide/dependency_resolution.html)
+ [Abhängigkeitsbeschränkungen und Konfliktlösung](https://docs.gradle.org/current/userguide/dependency_constraints_conflicts.html)
+ [Abstimmung der Abhängigkeitsversionen](https://docs.gradle.org/current/userguide/dependency_version_alignment.html)

## Verwaltung von SDK- und Smithy-Abhängigkeiten in Ihrem Projekt
<a name="sdk-smithy-dep-conflicts"></a>

Wenn Sie das SDK verwenden, denken Sie daran, dass seine Module in der Regel von anderen SDK-Modulen mit übereinstimmenden Versionsnummern abhängen. `aws.sdk.kotlin:s3:1.2.3`Hängt beispielsweise von a ab`ws.sdk.kotlin:aws-http:1.2.3`, das von abhängt`aws.sdk.kotlin:aws-core:1.2.3`, und so weiter.

Die SDK-Module verwenden auch spezifische Smithy-Modulversionen. Die Versionen des Smithy-Moduls werden zwar nicht mit den SDK-Versionsnummern synchronisiert, müssen aber mit der erwarteten Version des SDK übereinstimmen. `aws.sdk.kotlin:s3:1.2.3`Könnte zum Beispiel davon abhängen`aws.smithy.kotlin:serde:1.1.1`, was davon abhängt`aws.smithy.kotlin:runtime-core:1.1.1`, und so weiter.

Um Abhängigkeitskonflikte zu vermeiden, aktualisieren Sie alle Ihre SDK-Abhängigkeiten zusammen und tun Sie dasselbe für alle expliziten Smithy-Abhängigkeiten. Erwägen Sie die Verwendung unseres [Gradle-Versionskatalogs](setup-create-project-file.md), um Versionen synchron zu halten und Rätselraten bei der Zuordnung zwischen SDK- und Smithy-Versionen zu vermeiden.

[Denken Sie daran, dass kleinere Versionsupdates in SDK/Smithy Modulen grundlegende Änderungen beinhalten können, wie in unseren Versionierungsrichtlinien beschrieben.](https://github.com/awslabs/aws-sdk-kotlin/blob/main/VERSIONING.md#versioning-policy) Lesen Sie beim Upgrade zwischen Nebenversionen sorgfältig die Changelogs und testen Sie das Laufzeitverhalten gründlich.

## Lösung von OkHttp Versionskonflikten in Ihrer Anwendung
<a name="okhttp-dep-conflicts"></a>

[OkHttp](https://square.github.io/okhttp/)ist eine beliebte HTTP-Engine, die das SDK standardmäßig auf JVM verwendet. Ihre Anwendung kann andere Abhängigkeiten oder Frameworks enthalten, die eine andere OkHttp Version beinhalten. Dies kann dazu führen, dass Klassen im `okhttp3` Namespace nicht richtig angezeigt werden, z. B. `okhttp/coroutines/ExecuteAsyncKt` oder`okhttp3/ConnectionListener`. `NoClassDefFoundError` In diesem Fall sollten Sie generell die neuere Version wählen, um Konflikte zu lösen. Um Ihnen zu helfen, die Ursachen dieser Konflikte aufzuspüren, bietet Gradle eine nützliche Aufgabe. Sie können alle Abhängigkeiten auflisten, indem Sie Folgendes ausführen:

```
./gradlew dependencies
```

Wenn das SDK beispielsweise von einer anderen Abhängigkeit wie Spring Boot abhängt, OkHttp `4.12.0` sollten Sie die verwenden`5.0.0-alpha.14 version`. OkHttp `5.0.0-alpha.14` Sie können dies mit einem `constraints` Block in Gradle tun:

```
dependencies {
    constraints {
        implementation("com.squareup.okhttp3:okhttp:4.12.0")
    }
}
```

Wenn Sie OkHttp 4.x verwenden müssen, bietet das SDK alternativ eine. `OkHttp4Engine` In der [Dokumentation](https://github.com/smithy-lang/smithy-kotlin/tree/main/runtime/protocol/http-client-engines/http-client-engine-okhttp4) finden Sie Informationen zur Konfiguration und Verwendung von Gradle `OkHttp4Engine` in Ihrem Code.

# Spott in der AWS SDK für Kotlin
<a name="mocking"></a>

Entwickler können mehrere Frameworks verwenden, um Mocking in Tests mit dem durchzuführen. AWS SDK für Kotlin In diesem Thema werden zusätzliche Konfigurationen oder spezielle Überlegungen beschrieben, die für einige Frameworks erforderlich sind.

## MockK
<a name="mockk-consideration"></a>

[Wenn Sie modulweite Erweiterungsfunktionen mit [MockK](https://mockk.io/) simulieren, müssen Sie eine zusätzliche Konfiguration vornehmen.](https://mockk.io/#extension-functions) Im SDK für Kotlin sind Paginatoren, Waiters und Presigners Beispiele für Erweiterungsfunktionen. Wenn Sie sich also über ihr Verhalten lustig machen wollen, benötigen Sie eine zusätzliche Konfiguration.

Sie müssen anrufen, bevor Sie Ihre Mocks einrichten. `mockkStatic("<MODULE_CLASS_NAME>")` In der Regel lauten die Namen der Modulklassen: 
+ **Paginatoren**: `aws.sdk.kotlin.services.<service>.paginators.PaginatorsKt`
+ **Kellner:** `aws.sdk.kotlin.services.<service>.waiters.WaitersKt`
+ **Presignatoren**: `aws.sdk.kotlin.services.<service>.presigners.PresignersKt`

Im folgenden Test, der Mocking `listBucketsPaginated` — eine Funktion zur Erweiterung eines Paginators — beinhaltet, fügen wir beispielsweise hinzu: `mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")`

```
    @Test
    fun testPaginatedListBuckets() = runTest {

        mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")
        val s3Client: S3Client = mockk()
        val s3BucketLister = S3BucketLister(s3Client)

        val expectedBuckets = listOf(
            Bucket { name = "bucket1" },
            Bucket { name = "bucket2" }
        )

        val response = ListBucketsResponse { buckets = expectedBuckets }
        coEvery { s3Client.listBucketsPaginated() } returns flowOf(response)

        val result = s3BucketLister.getAllBucketNames()

        assertEquals(listOf("bucket1", "bucket2"), result)
    }
```

Ohne `mockkStatic` wird der folgende Fehler angezeigt:

```
Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
    at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
    at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
    at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:63)
    at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalCoEvery(API.kt:100)
    at io.mockk.MockKKt.coEvery(MockK.kt:174)
```

Bei einer Presigner-Erweiterungsfunktion ohne wird möglicherweise `mockkStatic` Folgendes angezeigt:

```
key is bound to the URI and must not be null
java.lang.IllegalArgumentException: key is bound to the URI and must not be null
    at aws.sdk.kotlin.services.s3.serde.GetObjectOperationSerializer.serialize(GetObjectOperationSerializer.kt:26)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject(Presigners.kt:49)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject$default(Presigners.kt:40)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject-exY8QGI(Presigners.kt:30)
```

### Alle Beispielartefakte
<a name="mockk-full-example"></a>

#### Code wird getestet
<a name="mockk-example-code-under-test"></a>

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.paginators.listBucketsPaginated
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.runBlocking
import org.slf4j.Logger
import org.slf4j.LoggerFactory

fun main() {
    val logger: Logger = LoggerFactory.getLogger(::main.javaClass)

    // Create an S3Client
    S3Client { region = "us-east-1" }.use { s3Client ->
        // Create service instance
        val bucketLister = S3BucketLister(s3Client)
        // Since getAllBucketNames is a suspend function, you'll need to run it in a coroutine scope
        runBlocking {
            val bucketNames = bucketLister.getAllBucketNames()
            logger.info("Found buckets: $bucketNames")
        }
    }
}

class S3BucketLister(private val s3Client: S3Client) {
    suspend fun getAllBucketNames(): List<String> {
        return s3Client.listBucketsPaginated()
            .transform { response ->
                response.buckets?.forEach { bucket ->
                    emit(bucket.name ?: "")
                }
            }
            .filter { it.isNotEmpty() }
            .toList()
    }
}
```

#### Klasse testen
<a name="mockk-example-test-code"></a>

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.Bucket
import aws.sdk.kotlin.services.s3.model.ListBucketsResponse
import aws.sdk.kotlin.services.s3.paginators.listBucketsPaginated
import io.mockk.coEvery
import io.mockk.mockk
import io.mockk.mockkStatic
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class S3BucketListerTest {

    @Test
    fun testPaginatedListBuckets() = runTest {

        mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")
        val s3Client: S3Client = mockk()
        val s3BucketLister = S3BucketLister(s3Client)

        val expectedBuckets = listOf(
            Bucket { name = "bucket1" },
            Bucket { name = "bucket2" }
        )

        val response = ListBucketsResponse { buckets = expectedBuckets }
        coEvery { s3Client.listBucketsPaginated() } returns flowOf(response)

        val result = s3BucketLister.getAllBucketNames()

        assertEquals(listOf("bucket1", "bucket2"), result)
    }
}
```

#### build.gradle.kts
<a name="mockk-example-gradle-build"></a>

```
plugins {
    kotlin("jvm") version "2.1.20"
    application
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(platform(awssdk.bom))
    implementation(platform("org.apache.logging.log4j:log4j-bom:2.24.3"))

    implementation(awssdk.services.s3)
    implementation("org.apache.logging.log4j:log4j-slf4j2-impl")

    // Testing Dependencies
    testImplementation(platform("org.junit:junit-bom:5.11.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
    testImplementation("io.mockk:mockk:1.14.0")
}

tasks.test {
    useJUnitPlatform()
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

application {
    mainClass = "org.example.S3BucketService"
}
```

#### Einstellungen.gradle.kts
<a name="mockk-example-settings-build"></a>

```
plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
}
rootProject.name = "mockK-static"

dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }

    versionCatalogs {
        create("awssdk") {
            from("aws.sdk.kotlin:version-catalog:1.4.69")
        }
    }
}
```