

Dies ist der AWS CDK v2-Entwicklerhandbuch. Das ältere CDK v1 wurde am 1. Juni 2022 gewartet und der Support wurde am 1. Juni 2023 eingestellt.

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.

# Testen Sie AWS CDK-Anwendungen
<a name="testing"></a>

Mit dem AWS CDK kann Ihre Infrastruktur genauso testbar sein wie jeder andere Code, den Sie schreiben. Sie können in der Cloud und lokal testen. In diesem Thema wird beschrieben, wie Sie in der Cloud testen können. Hinweise zu lokalen Tests finden Sie unter [Lokales Testen und Erstellen von AWS CDK-Anwendungen mit der AWS SAM-CLI](testing-locally.md). [Der Standardansatz zum Testen von AWS CDK-Apps verwendet das [Assertionsmodul](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html) des AWS CDK und beliebte Testframeworks wie [Jest](https://jestjs.io/) for und/oder JavaScript oder Pytest for TypeScript Python.](https://docs.pytest.org/en/6.2.x/)

Es gibt zwei Kategorien von Tests, die Sie für CDK-Apps schreiben können. AWS 
+  **Präzise Assertionen** testen bestimmte Aspekte der generierten AWS CloudFormation Vorlage, z. B. „Diese Ressource hat diese Eigenschaft mit diesem Wert“. Diese Tests können Regressionen erkennen. Sie sind auch nützlich, wenn Sie mithilfe der testgetriebenen Entwicklung neue Funktionen entwickeln. (Sie können zuerst einen Test schreiben und ihn dann bestehen lassen, indem Sie eine korrekte Implementierung schreiben.) Feinkörnige Assertionen sind die am häufigsten verwendeten Tests.
+  **Snapshot-Tests** testen das synthetisierte AWS CloudFormation Template mit einem zuvor gespeicherten Baseline-Template. Mit Snapshot-Tests können Sie frei umgestalten, da Sie sicher sein können, dass der umgestaltete Code genauso funktioniert wie das Original. Wenn die Änderungen beabsichtigt waren, können Sie eine neue Ausgangsbasis für zukünftige Tests akzeptieren. CDK-Upgrades können jedoch auch dazu führen, dass sich synthetisierte Vorlagen ändern, sodass Sie sich nicht nur auf Snapshots verlassen können, um sicherzustellen, dass Ihre Implementierung korrekt ist.

**Anmerkung**  
Vollständige Versionen der TypeScript Python- und Java-Apps, die in diesem Thema als Beispiele verwendet werden, sind [unter verfügbar GitHub](https://github.com/cdklabs/aws-cdk-testing-examples/).

## Erste Schritte
<a name="testing-getting-started"></a>

Um zu veranschaulichen, wie diese Tests geschrieben werden, erstellen wir einen Stack, der eine AWS Step Functions Functions-Zustandsmaschine und eine AWS Lambda-Funktion enthält. Die Lambda-Funktion abonniert ein Amazon SNS SNS-Thema und leitet die Nachricht einfach an die Zustandsmaschine weiter.

Erstellen Sie zunächst mit dem CDK-Toolkit ein leeres CDK-Anwendungsprojekt und installieren Sie die benötigten Bibliotheken. Die Konstrukte, die wir verwenden werden, befinden sich alle im CDK-Hauptpaket, was eine Standardabhängigkeit in Projekten ist, die mit dem CDK-Toolkit erstellt wurden. Sie müssen jedoch Ihr Test-Framework installieren.

**Example**  

```
$ mkdir state-machine && cd state-machine
cdk init --language=typescript
npm install --save-dev jest @types/jest
```
Erstellen Sie ein Verzeichnis für Ihre Tests.  

```
$ mkdir test
```
Bearbeiten Sie die Projekte`package.json`, um NPM mitzuteilen, wie Jest ausgeführt werden soll, und um Jest mitzuteilen, welche Arten von Dateien gesammelt werden sollen. Die erforderlichen Änderungen lauten wie folgt.  
+ Fügen Sie dem `scripts` Abschnitt einen neuen `test` Schlüssel hinzu
+ Fügen Sie Jest und seine Typen zum `devDependencies` Abschnitt hinzu
+ Fügen Sie einen neuen Schlüssel der `jest` obersten Ebene mit einer Deklaration hinzu `moduleFileExtensions`
Diese Änderungen werden in der folgenden Übersicht dargestellt. Platzieren Sie den neuen Text an der unter angegebenen Stelle`package.json`. Die Platzhalter „...“ stehen für vorhandene Teile der Datei, die nicht geändert werden sollten.  

```
{
  ...
  "scripts": {
    ...
    "test": "jest"
  },
  "devDependencies": {
    ...
    "@types/jest": "^24.0.18",
    "jest": "^24.9.0"
  },
  "jest": {
    "moduleFileExtensions": ["js"]
  }
}
```

```
$ mkdir state-machine && cd state-machine
$ cdk init --language=javascript
$ npm install --save-dev jest
```
Erstellen Sie ein Verzeichnis für Ihre Tests.  

```
$ mkdir test
```
Bearbeiten Sie die Projekte`package.json`, um NPM mitzuteilen, wie Jest ausgeführt werden soll, und um Jest mitzuteilen, welche Arten von Dateien gesammelt werden sollen. Die erforderlichen Änderungen lauten wie folgt.  
+ Fügen Sie dem `scripts` Abschnitt einen neuen `test` Schlüssel hinzu
+ Füge Jest zum Abschnitt hinzu `devDependencies`
+ Fügen Sie einen neuen Schlüssel der `jest` obersten Ebene mit einer Deklaration hinzu `moduleFileExtensions`
Diese Änderungen werden in der folgenden Übersicht dargestellt. Platzieren Sie den neuen Text an der unter angegebenen Stelle`package.json`. Die Platzhalter „...“ stehen für vorhandene Teile der Datei, die nicht geändert werden sollten.  

```
{
  ...
  "scripts": {
    ...
    "test": "jest"
  },
  "devDependencies": {
    ...
    "jest": "^24.9.0"
  },
  "jest": {
    "moduleFileExtensions": ["js"]
  }
}
```

```
$ mkdir state-machine && cd state-machine
$ cdk init --language=python
$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead
$ python -m pip install -r requirements.txt
$ python -m pip install -r requirements-dev.txt
```

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=java
```
Öffnen Sie das Projekt in Ihrer bevorzugten Java-IDE. (Verwenden Sie in Eclipse „**Datei**“ > **„Importieren“ > „**Bestehende Maven-Projekte“.)

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=csharp
```
`src\StateMachine.sln`In Visual Studio öffnen.  
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Lösung und wählen **Sie Hinzufügen** > **Neues Projekt**. Suchen Sie nach MSTest C\$1 und fügen Sie ein **MSTest Testprojekt** für C\$1 hinzu. (Der Standardname `TestProject1` ist in Ordnung.)  
Klicken Sie mit der rechten Maustaste`TestProject1`, wählen **Sie Hinzufügen** > **Projektreferenz** und fügen Sie das `StateMachine` Projekt als Referenz hinzu.

## Der Beispielstapel
<a name="testing-app"></a>

Hier ist der Stack, der in diesem Thema getestet wird. Wie bereits beschrieben, enthält es eine Lambda-Funktion und eine Step Functions Functions-Zustandsmaschine und akzeptiert ein oder mehrere Amazon SNS SNS-Themen. Die Lambda-Funktion abonniert die Amazon SNS SNS-Themen und leitet sie an die Zustandsmaschine weiter.

Sie müssen nichts Besonderes tun, um die App testbar zu machen. Tatsächlich unterscheidet sich dieser CDK-Stack in keiner wichtigen Weise von den anderen Beispielstapeln in diesem Handbuch.

**Example**  
Fügen Sie den folgenden Code ein: `lib/state-machine-stack.ts`  

```
import * as cdk from "aws-cdk-lib";
import * as sns from "aws-cdk-lib/aws-sns";
import * as sns_subscriptions from "aws-cdk-lib/aws-sns-subscriptions";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as sfn from "aws-cdk-lib/aws-stepfunctions";
import { Construct } from "constructs";

export interface StateMachineStackProps extends cdk.StackProps {
  readonly topics: sns.Topic[];
}

export class StateMachineStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: StateMachineStackProps) {
    super(scope, id, props);

    // In the future this state machine will do some work...
    const stateMachine = new sfn.StateMachine(this, "StateMachine", {
      definition: new sfn.Pass(this, "StartState"),
    });

    // This Lambda function starts the state machine.
    const func = new lambda.Function(this, "LambdaFunction", {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: "handler",
      code: lambda.Code.fromAsset("./start-state-machine"),
      environment: {
        STATE_MACHINE_ARN: stateMachine.stateMachineArn,
      },
    });
    stateMachine.grants.startExecution(func);

    const subscription = new sns_subscriptions.LambdaSubscription(func);
    for (const topic of props.topics) {
      topic.addSubscription(subscription);
    }
  }
}
```
Geben Sie den folgenden Code ein`lib/state-machine-stack.js`:  

```
const cdk = require("aws-cdk-lib");
const sns = require("aws-cdk-lib/aws-sns");
const sns_subscriptions = require("aws-cdk-lib/aws-sns-subscriptions");
const lambda = require("aws-cdk-lib/aws-lambda");
const sfn = require("aws-cdk-lib/aws-stepfunctions");

class StateMachineStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // In the future this state machine will do some work...
    const stateMachine = new sfn.StateMachine(this, "StateMachine", {
      definition: new sfn.Pass(this, "StartState"),
    });

    // This Lambda function starts the state machine.
    const func = new lambda.Function(this, "LambdaFunction", {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: "handler",
      code: lambda.Code.fromAsset("./start-state-machine"),
      environment: {
        STATE_MACHINE_ARN: stateMachine.stateMachineArn,
      },
    });
    stateMachine.grants.startExecution(func);

    const subscription = new sns_subscriptions.LambdaSubscription(func);
    for (const topic of props.topics) {
      topic.addSubscription(subscription);
    }
  }
}

module.exports = { StateMachineStack }
```
Geben Sie den folgenden Code ein`state_machine/state_machine_stack.py`:  

```
from typing import List

import aws_cdk.aws_lambda as lambda_
import aws_cdk.aws_sns as sns
import aws_cdk.aws_sns_subscriptions as sns_subscriptions
import aws_cdk.aws_stepfunctions as sfn
import aws_cdk as cdk

class StateMachineStack(cdk.Stack):
    def __init__(
        self,
        scope: cdk.Construct,
        construct_id: str,
        *,
        topics: List[sns.Topic],
        **kwargs
    ) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # In the future this state machine will do some work...
        state_machine = sfn.StateMachine(
            self, "StateMachine", definition=sfn.Pass(self, "StartState")
        )

        # This Lambda function starts the state machine.
        func = lambda_.Function(
            self,
            "LambdaFunction",
            runtime=lambda_.Runtime.NODEJS_18_X,
            handler="handler",
            code=lambda_.Code.from_asset("./start-state-machine"),
            environment={
                "STATE_MACHINE_ARN": state_machine.state_machine_arn,
            },
        )
        state_machine.grants.start_execution(func)

        subscription = sns_subscriptions.LambdaSubscription(func)
        for topic in topics:
            topic.add_subscription(subscription)
```

```
package software.amazon.samples.awscdkassertionssamples;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.sns.ITopicSubscription;
import software.amazon.awscdk.services.sns.Topic;
import software.amazon.awscdk.services.sns.subscriptions.LambdaSubscription;
import software.amazon.awscdk.services.stepfunctions.Pass;
import software.amazon.awscdk.services.stepfunctions.StateMachine;

import java.util.Collections;
import java.util.List;

public class StateMachineStack extends Stack {
    public StateMachineStack(final Construct scope, final String id, final List<Topic> topics) {
        this(scope, id, null, topics);
    }

    public StateMachineStack(final Construct scope, final String id, final StackProps props, final List<Topic> topics) {
        super(scope, id, props);

        // In the future this state machine will do some work...
        final StateMachine stateMachine = StateMachine.Builder.create(this, "StateMachine")
                .definition(new Pass(this, "StartState"))
                .build();

        // This Lambda function starts the state machine.
        final Function func = Function.Builder.create(this, "LambdaFunction")
                .runtime(Runtime.NODEJS_18_X)
                .handler("handler")
                .code(Code.fromAsset("./start-state-machine"))
                .environment(Collections.singletonMap("STATE_MACHINE_ARN", stateMachine.getStateMachineArn()))
                .build();
        stateMachine.getGrants().startExecution(func);

        final ITopicSubscription subscription = new LambdaSubscription(func);
        for (final Topic topic : topics) {
            topic.addSubscription(subscription);
        }
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.StepFunctions;
using Amazon.CDK.AWS.SNS;
using Amazon.CDK.AWS.SNS.Subscriptions;
using Constructs;

using System.Collections.Generic;

namespace AwsCdkAssertionSamples
{
    public class StateMachineStackProps : StackProps
    {
        public Topic[] Topics;
    }

    public class StateMachineStack : Stack
    {

        internal StateMachineStack(Construct scope, string id, StateMachineStackProps props = null) : base(scope, id, props)
        {
            // In the future this state machine will do some work...
            var stateMachine = new StateMachine(this, "StateMachine", new StateMachineProps
            {
                Definition = new Pass(this, "StartState")
            });

            // This Lambda function starts the state machine.
            var func = new Function(this, "LambdaFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_18_X,
                Handler = "handler",
                Code = Code.FromAsset("./start-state-machine"),
                Environment = new Dictionary<string, string>
                {
                    { "STATE_MACHINE_ARN", stateMachine.StateMachineArn }
                }
            });
            stateMachine.Grants.StartExecution(func);

            foreach (Topic topic in props?.Topics ?? new Topic[0])
            {
                var subscription = new LambdaSubscription(func);
            }

        }
    }
}
```

Wir werden den Haupteinstiegspunkt der App so ändern, dass wir unseren Stack nicht wirklich instanziieren. Wir wollen es nicht versehentlich bereitstellen. Unsere Tests werden eine App und eine Instanz des Stacks zum Testen erstellen. In Kombination mit testgetriebener Entwicklung ist dies eine nützliche Taktik: Stellen Sie sicher, dass der Stack alle Tests besteht, bevor Sie die Bereitstellung aktivieren.

**Example**  
In `bin/state-machine.ts`:  

```
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";

const app = new cdk.App();

// Stacks are intentionally not created here -- this application isn't meant to
// be deployed.
```
In `bin/state-machine.js`:  

```
#!/usr/bin/env node
const cdk = require("aws-cdk-lib");

const app = new cdk.App();

// Stacks are intentionally not created here -- this application isn't meant to
// be deployed.
```
In `app.py`:  

```
#!/usr/bin/env python3
import os

import aws_cdk  as cdk

app = cdk.App()

# Stacks are intentionally not created here -- this application isn't meant to
# be deployed.

app.synth()
```

```
package software.amazon.samples.awscdkassertionssamples;

import software.amazon.awscdk.App;

public class SampleApp {
    public static void main(final String[] args) {
        App app = new App();

        // Stacks are intentionally not created here -- this application isn't meant to be deployed.

        app.synth();
    }
}
```

```
using Amazon.CDK;

namespace AwsCdkAssertionSamples
{
    sealed class Program
    {
        public static void Main(string[] args)
        {
            var app = new App();

            // Stacks are intentionally not created here -- this application isn't meant to be deployed.

            app.Synth();
        }
    }
}
```

## Die Lambda-Funktion
<a name="testing-lambda"></a>

Unser Beispielstapel enthält eine Lambda-Funktion, die unsere Zustandsmaschine startet. Wir müssen den Quellcode für diese Funktion bereitstellen, damit das CDK ihn als Teil der Erstellung der Lambda-Funktionsressource bündeln und bereitstellen kann.
+ Erstellen Sie den Ordner `start-state-machine` im Hauptverzeichnis der App.
+ Erstellen Sie in diesem Ordner mindestens eine Datei. Sie können beispielsweise den folgenden Code in speichern`start-state-machines/index.js`.

  ```
  exports.handler = async function (event, context) {
  	return 'hello world';
  };
  ```

  Es wird jedoch jede Datei funktionieren, da wir den Stack nicht wirklich bereitstellen werden.

## Ausführen von Tests
<a name="testing-running-tests"></a>

Als Referenz finden Sie hier die Befehle, mit denen Sie Tests in Ihrer AWS CDK-App ausführen. Dies sind dieselben Befehle, die Sie verwenden würden, um die Tests in jedem Projekt mit demselben Testframework auszuführen. Fügen Sie bei Sprachen, die einen Build-Schritt erfordern, diesen hinzu, um sicherzustellen, dass Ihre Tests kompiliert wurden.

**Example**  

```
$ tsc && npm test
```

```
$ npm test
```

```
$ python -m pytest
```

```
$ mvn compile && mvn test
```
Erstellen Sie Ihre Lösung (F6), um die Tests zu ermitteln, und führen Sie dann die Tests aus (**Test** > **Alle Tests ausführen**). Um auszuwählen, welche Tests ausgeführt werden sollen, öffnen Sie den Test Explorer (**Test** > **Test Explorer**).  
Oder:  

```
$ dotnet test src
```

## Fein abgestufte Behauptungen
<a name="testing-fine-grained"></a>

Der erste Schritt zum Testen eines Stacks mit feinkörnigen Assertionen besteht darin, den Stack zu synthetisieren, da wir Assertionen anhand der generierten Vorlage schreiben. AWS CloudFormation 

Unser `StateMachineStackStack` verlangt, dass wir ihm das Amazon SNS SNS-Thema übergeben, damit es an den Zustandsmaschine weitergeleitet wird. In unserem Test erstellen wir also einen separaten Stapel, der das Thema enthält.

Normalerweise können Sie beim Schreiben einer CDK-App das Amazon SNS SNS-Thema im `Stack` Konstruktor des Stacks unterordnen und instanziieren. In unserem Test instanziieren wir `Stack` direkt, übergeben diesen Stack dann als Gültigkeitsbereich und hängen ihn an den `Topic` Stack an. Das ist funktionell äquivalent und weniger ausführlich. Es trägt auch dazu bei, dass Stacks, die nur in Tests verwendet werden, „anders aussehen“ als die Stacks, die Sie bereitstellen möchten.

**Example**  

```
import { Capture, Match, Template } from "aws-cdk-lib/assertions";
import * as cdk from "aws-cdk-lib";
import * as sns from "aws-cdk-lib/aws-sns";
import { StateMachineStack } from "../lib/state-machine-stack";

describe("StateMachineStack", () => {
  test("synthesizes the way we expect", () => {
    const app = new cdk.App();

    // Since the StateMachineStack consumes resources from a separate stack
    // (cross-stack references), we create a stack for our SNS topics to live
    // in here. These topics can then be passed to the StateMachineStack later,
    // creating a cross-stack reference.
    const topicsStack = new cdk.Stack(app, "TopicsStack");

    // Create the topic the stack we're testing will reference.
    const topics = [new sns.Topic(topicsStack, "Topic1", {})];

    // Create the StateMachineStack.
    const stateMachineStack = new StateMachineStack(app, "StateMachineStack", {
      topics: topics, // Cross-stack reference
    });

    // Prepare the stack for assertions.
    const template = Template.fromStack(stateMachineStack);
  })
})
```

```
const { Capture, Match, Template } = require("aws-cdk-lib/assertions");
const cdk = require("aws-cdk-lib");
const sns = require("aws-cdk-lib/aws-sns");
const { StateMachineStack } = require("../lib/state-machine-stack");

describe("StateMachineStack", () => {
  test("synthesizes the way we expect", () => {
    const app = new cdk.App();

    // Since the StateMachineStack consumes resources from a separate stack
    // (cross-stack references), we create a stack for our SNS topics to live
    // in here. These topics can then be passed to the StateMachineStack later,
    // creating a cross-stack reference.
    const topicsStack = new cdk.Stack(app, "TopicsStack");

    // Create the topic the stack we're testing will reference.
    const topics = [new sns.Topic(topicsStack, "Topic1", {})];

    // Create the StateMachineStack.
    const StateMachineStack = new StateMachineStack(app, "StateMachineStack", {
      topics: topics, // Cross-stack reference
    });

    // Prepare the stack for assertions.
    const template = Template.fromStack(stateMachineStack);
  })
})
```

```
from aws_cdk import aws_sns as sns
import aws_cdk as cdk
from aws_cdk.assertions import Template

from app.state_machine_stack import StateMachineStack

def test_synthesizes_properly():
    app = cdk.App()

    # Since the StateMachineStack consumes resources from a separate stack
    # (cross-stack references), we create a stack for our SNS topics to live
    # in here. These topics can then be passed to the StateMachineStack later,
    # creating a cross-stack reference.
    topics_stack = cdk.Stack(app, "TopicsStack")

    # Create the topic the stack we're testing will reference.
    topics = [sns.Topic(topics_stack, "Topic1")]

    # Create the StateMachineStack.
    state_machine_stack = StateMachineStack(
        app, "StateMachineStack", topics=topics  # Cross-stack reference
    )

    # Prepare the stack for assertions.
    template = Template.from_stack(state_machine_stack)
```

```
package software.amazon.samples.awscdkassertionssamples;

import org.junit.jupiter.api.Test;
import software.amazon.awscdk.assertions.Capture;
import software.amazon.awscdk.assertions.Match;
import software.amazon.awscdk.assertions.Template;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.services.sns.Topic;

import java.util.*;

import static org.assertj.core.api.Assertions.assertThat;

public class StateMachineStackTest {
    @Test
    public void testSynthesizesProperly() {
        final App app = new App();

        // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack
        // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a
        // cross-stack reference.
        final Stack topicsStack = new Stack(app, "TopicsStack");

        // Create the topic the stack we're testing will reference.
        final List<Topic> topics = Collections.singletonList(Topic.Builder.create(topicsStack, "Topic1").build());

        // Create the StateMachineStack.
        final StateMachineStack stateMachineStack = new StateMachineStack(
                app,
                "StateMachineStack",
                topics // Cross-stack reference
        );

        // Prepare the stack for assertions.
        final Template template = Template.fromStack(stateMachineStack)
    }
}
```

```
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Amazon.CDK;
using Amazon.CDK.AWS.SNS;
using Amazon.CDK.Assertions;
using AwsCdkAssertionSamples;

using ObjectDict = System.Collections.Generic.Dictionary<string, object>;
using StringDict = System.Collections.Generic.Dictionary<string, string>;

namespace TestProject1
{
    [TestClass]
    public class StateMachineStackTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            var app = new App();

            // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack
            // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a
            // cross-stack reference.
            var topicsStack = new Stack(app, "TopicsStack");

            // Create the topic the stack we're testing will reference.
            var topics = new Topic[] { new Topic(topicsStack, "Topic1") };

            // Create the StateMachineStack.
            var StateMachineStack = new StateMachineStack(app, "StateMachineStack", new StateMachineStackProps
            {
                Topics = topics
            });

            // Prepare the stack for assertions.
            var template = Template.FromStack(stateMachineStack);

            // test will go here
        }
    }
}
```

Jetzt können wir behaupten, dass die Lambda-Funktion und das Amazon SNS SNS-Abonnement erstellt wurden.

**Example**  

```
    // Assert it creates the function with the correct properties...
    template.hasResourceProperties("AWS::Lambda::Function", {
      Handler: "handler",
      Runtime: "nodejs14.x",
    });

    // Creates the subscription...
    template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
    // Assert it creates the function with the correct properties...
    template.hasResourceProperties("AWS::Lambda::Function", {
      Handler: "handler",
      Runtime: "nodejs14.x",
    });

    // Creates the subscription...
    template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
# Assert that we have created the function with the correct properties
    template.has_resource_properties(
        "AWS::Lambda::Function",
        {
            "Handler": "handler",
            "Runtime": "nodejs14.x",
        },
    )

    # Assert that we have created a subscription
    template.resource_count_is("AWS::SNS::Subscription", 1)
```

```
        // Assert it creates the function with the correct properties...
        template.hasResourceProperties("AWS::Lambda::Function", Map.of(
                "Handler", "handler",
                "Runtime", "nodejs14.x"
        ));

         // Creates the subscription...
        template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
            // Prepare the stack for assertions.
            var template = Template.FromStack(stateMachineStack);

            // Assert it creates the function with the correct properties...
            template.HasResourceProperties("AWS::Lambda::Function", new StringDict {
                { "Handler", "handler"},
                { "Runtime", "nodejs14x" }
            });

            // Creates the subscription...
            template.ResourceCountIs("AWS::SNS::Subscription", 1);
```

Unser Lambda-Funktionstest bestätigt, dass zwei bestimmte Eigenschaften der Funktionsressource spezifische Werte haben. Standardmäßig führt die `hasResourceProperties` Methode eine teilweise Übereinstimmung der Eigenschaften der Ressource durch, wie sie in der synthetisierten CloudFormation Vorlage angegeben sind. Dieser Test setzt voraus, dass die angegebenen Eigenschaften vorhanden sind und die angegebenen Werte haben. Die Ressource kann jedoch auch andere Eigenschaften haben, die nicht getestet wurden.

Unsere Amazon SNS SNS-Behauptung behauptet, dass die synthetisierte Vorlage ein Abonnement enthält, aber nichts über das Abonnement selbst. Wir haben diese Behauptung hauptsächlich aufgenommen, um zu veranschaulichen, wie die Anzahl der Ressourcen bestätigt werden kann. Die `Template` Klasse bietet spezifischere Methoden, um Assertions für die `Mapping` Abschnitte `Resources``Outputs`, und der CloudFormation Vorlage zu schreiben.<a name="testing-fine-grained-matchers"></a>

 **Matcher**   
Das standardmäßige Verhalten bei teilweisem Abgleich von `hasResourceProperties` kann mithilfe von *Matchern* aus der ` [Match](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods) ` Klasse geändert werden.  
Die Übereinstimmungen reichen von lenient (`Match.anyValue`) bis strikt (). `Match.objectEquals` Sie können verschachtelt werden, um unterschiedliche Abgleichmethoden auf verschiedene Teile der Ressourceneigenschaften anzuwenden. Mithilfe von `Match.objectEquals` und `Match.anyValue` zusammen können wir beispielsweise die IAM-Rolle der Zustandsmaschine umfassender testen, ohne dass spezifische Werte für Eigenschaften erforderlich sind, die sich ändern könnten.  

**Example**  

```
    // Fully assert on the state machine's IAM role with matchers.
    template.hasResourceProperties(
      "AWS::IAM::Role",
      Match.objectEquals({
        AssumeRolePolicyDocument: {
          Version: "2012-10-17",		 	 	 
          Statement: [
            {
              Action: "sts:AssumeRole",
              Effect: "Allow",
              Principal: {
                Service: {
                  "Fn::Join": [
                    "",
                    ["states.", Match.anyValue(), ".amazonaws.com"],
                  ],
                },
              },
            },
          ],
        },
      })
    );
```

```
    // Fully assert on the state machine's IAM role with matchers.
    template.hasResourceProperties(
      "AWS::IAM::Role",
      Match.objectEquals({
        AssumeRolePolicyDocument: {
          Version: "2012-10-17",		 	 	 
          Statement: [
            {
              Action: "sts:AssumeRole",
              Effect: "Allow",
              Principal: {
                Service: {
                  "Fn::Join": [
                    "",
                    ["states.", Match.anyValue(), ".amazonaws.com"],
                  ],
                },
              },
            },
          ],
        },
      })
    );
```

```
from aws_cdk.assertions import Match

    # Fully assert on the state machine's IAM role with matchers.
    template.has_resource_properties(
        "AWS::IAM::Role",
        Match.object_equals(
            {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Action": "sts:AssumeRole",
                            "Effect": "Allow",
                            "Principal": {
                                "Service": {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "states.",
                                            Match.any_value(),
                                            ".amazonaws.com",
                                        ],
                                    ],
                                },
                            },
                        },
                    ],
                },
            }
        ),
    )
```

```
        // Fully assert on the state machine's IAM role with matchers.
        template.hasResourceProperties("AWS::IAM::Role", Match.objectEquals(
                Collections.singletonMap("AssumeRolePolicyDocument", Map.of(
                        "Version", "2012-10-17",		 	 	 
                        "Statement", Collections.singletonList(Map.of(
                                "Action", "sts:AssumeRole",
                                "Effect", "Allow",
                                "Principal", Collections.singletonMap(
                                        "Service", Collections.singletonMap(
                                                "Fn::Join", Arrays.asList(
                                                        "",
                                                        Arrays.asList("states.", Match.anyValue(), ".amazonaws.com")
                                                )
                                        )
                                )
                        ))
                ))
        ));
```

```
            // Fully assert on the state machine's IAM role with matchers.
            template.HasResource("AWS::IAM::Role", Match.ObjectEquals(new ObjectDict
            {
                { "AssumeRolePolicyDocument", new ObjectDict
                    {
                        { "Version", "2012-10-17"		 	 	  },
                        { "Action", "sts:AssumeRole" },
                        { "Principal", new ObjectDict
                            {
                                { "Version", "2012-10-17"		 	 	  },
                                { "Statement", new object[]
                                    {
                                        new ObjectDict {
                                            { "Action", "sts:AssumeRole" },
                                            { "Effect", "Allow" },
                                            { "Principal", new ObjectDict
                                                {
                                                    { "Service", new ObjectDict
                                                        {
                                                            { "", new object[]
                                                                { "states", Match.AnyValue(), ".amazonaws.com" }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }));
```
Viele CloudFormation Ressourcen enthalten serialisierte JSON-Objekte, die als Zeichenketten dargestellt werden. Der `Match.serializedJson()` Matcher kann verwendet werden, um Eigenschaften in diesem JSON abzugleichen.  
Beispielsweise werden Step Functions Functions-Zustandsmaschinen mithilfe einer Zeichenfolge in der JSON-basierten [Amazon States-Sprache definiert.](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) Damit stellen wir sicher`Match.serializedJson()`, dass unser Ausgangsstatus der einzige Schritt ist. Auch hier verwenden wir verschachtelte Matcher, um verschiedene Arten der Zuordnung auf verschiedene Teile des Objekts anzuwenden.  

**Example**  

```
    // Assert on the state machine's definition with the Match.serializedJson()
    // matcher.
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        // Match.objectEquals() is used implicitly, but we use it explicitly
        // here for extra clarity.
        Match.objectEquals({
          StartAt: "StartState",
          States: {
            StartState: {
              Type: "Pass",
              End: true,
              // Make sure this state doesn't provide a next state -- we can't
              // provide both Next and set End to true.
              Next: Match.absent(),
            },
          },
        })
      ),
    });
```

```
    // Assert on the state machine's definition with the Match.serializedJson()
    // matcher.
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        // Match.objectEquals() is used implicitly, but we use it explicitly
        // here for extra clarity.
        Match.objectEquals({
          StartAt: "StartState",
          States: {
            StartState: {
              Type: "Pass",
              End: true,
              // Make sure this state doesn't provide a next state -- we can't
              // provide both Next and set End to true.
              Next: Match.absent(),
            },
          },
        })
      ),
    });
```

```
    # Assert on the state machine's definition with the serialized_json matcher.
    template.has_resource_properties(
        "AWS::StepFunctions::StateMachine",
        {
            "DefinitionString": Match.serialized_json(
                # Match.object_equals() is the default, but specify it here for clarity
                Match.object_equals(
                    {
                        "StartAt": "StartState",
                        "States": {
                            "StartState": {
                                "Type": "Pass",
                                "End": True,
                                # Make sure this state doesn't provide a next state --
                                # we can't provide both Next and set End to true.
                                "Next": Match.absent(),
                            },
                        },
                    }
                )
            ),
        },
    )
```

```
        // Assert on the state machine's definition with the Match.serializedJson() matcher.
        template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap(
                "DefinitionString", Match.serializedJson(
                        // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity.
                        Match.objectEquals(Map.of(
                                "StartAt", "StartState",
                                "States", Collections.singletonMap(
                                        "StartState", Map.of(
                                                "Type", "Pass",
                                                "End", true,
                                                // Make sure this state doesn't provide a next state -- we can't provide
                                                // both Next and set End to true.
                                                "Next", Match.absent()
                                        )
                                )
                        ))
                )
        ));
```

```
            // Assert on the state machine's definition with the Match.serializedJson() matcher
            template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict
            {
                { "DefinitionString", Match.SerializedJson(
                    // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity.
                    Match.ObjectEquals(new ObjectDict {
                        { "StartAt", "StartState" },
                        { "States", new ObjectDict
                        {
                            { "StartState", new ObjectDict {
                                { "Type", "Pass" },
                                { "End", "True" },
                                // Make sure this state doesn't provide a next state -- we can't provide
                                // both Next and set End to true.
                                { "Next", Match.Absent() }
                            }}
                        }}
                    })
                )}});
```<a name="testing-fine-grained-capture"></a>

 **Erfassen**   
Es ist oft nützlich, Eigenschaften zu testen, um sicherzustellen, dass sie bestimmten Formaten entsprechen oder denselben Wert wie eine andere Eigenschaft haben, ohne ihre genauen Werte im Voraus kennen zu müssen. Das `assertions` Modul bietet diese Funktion in seiner ` [Capture](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html) ` Klasse.  
Durch die Angabe einer `Capture` Instanz anstelle eines Werts in `hasResourceProperties` wird dieser Wert im `Capture` Objekt beibehalten. Der tatsächlich erfasste Wert kann mit den `as` Methoden des Objekts, einschließlich`asNumber()`, und `asString()``asObject`, abgerufen und einem Test unterzogen werden. Verwenden Sie `Capture` ihn zusammen mit einem Matcher, um die genaue Position des zu erfassenden Werts in den Eigenschaften der Ressource, einschließlich serialisierter JSON-Eigenschaften, anzugeben.  
Das folgende Beispiel testet, ob der Startstatus unserer Zustandsmaschine einen Namen hat, der mit beginnt. `Start` Es testet auch, ob dieser Status in der Liste der Zustände in der Maschine vorhanden ist.  

**Example**  

```
    // Capture some data from the state machine's definition.
    const startAtCapture = new Capture();
    const statesCapture = new Capture();
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        Match.objectLike({
          StartAt: startAtCapture,
          States: statesCapture,
        })
      ),
    });

    // Assert that the start state starts with "Start".
    expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/));

    // Assert that the start state actually exists in the states object of the
    // state machine definition.
    expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());
```

```
    // Capture some data from the state machine's definition.
    const startAtCapture = new Capture();
    const statesCapture = new Capture();
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        Match.objectLike({
          StartAt: startAtCapture,
          States: statesCapture,
        })
      ),
    });

    // Assert that the start state starts with "Start".
    expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/));

    // Assert that the start state actually exists in the states object of the
    // state machine definition.
    expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());
```

```
import re

    from aws_cdk.assertions import Capture

    # ...

    # Capture some data from the state machine's definition.
    start_at_capture = Capture()
    states_capture = Capture()
    template.has_resource_properties(
        "AWS::StepFunctions::StateMachine",
        {
            "DefinitionString": Match.serialized_json(
                Match.object_like(
                    {
                        "StartAt": start_at_capture,
                        "States": states_capture,
                    }
                )
            ),
        },
    )

    # Assert that the start state starts with "Start".
    assert re.match("^Start", start_at_capture.as_string())

    # Assert that the start state actually exists in the states object of the
    # state machine definition.
    assert start_at_capture.as_string() in states_capture.as_object()
```

```
        // Capture some data from the state machine's definition.
        final Capture startAtCapture = new Capture();
        final Capture statesCapture = new Capture();
        template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap(
                "DefinitionString", Match.serializedJson(
                        Match.objectLike(Map.of(
                                "StartAt", startAtCapture,
                                "States", statesCapture
                        ))
                )
        ));

        // Assert that the start state starts with "Start".
        assertThat(startAtCapture.asString()).matches("^Start.+");

        // Assert that the start state actually exists in the states object of the state machine definition.
        assertThat(statesCapture.asObject()).containsKey(startAtCapture.asString());
```

```
            // Capture some data from the state machine's definition.
            var startAtCapture = new Capture();
            var statesCapture = new Capture();
            template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict
            {
                { "DefinitionString", Match.SerializedJson(
                    new ObjectDict
                    {
                        { "StartAt", startAtCapture },
                        { "States", statesCapture }
                    }
                )}
            });

            Assert.IsTrue(startAtCapture.ToString().StartsWith("Start"));
            Assert.IsTrue(statesCapture.AsObject().ContainsKey(startAtCapture.ToString()));
```

## Snapshot-Tests
<a name="testing-snapshot"></a>

Beim *Snapshot-Testen* vergleichen Sie die gesamte synthetisierte CloudFormation Vorlage mit einer zuvor gespeicherten Baseline-Vorlage (oft als „Master“ bezeichnet). Im Gegensatz zu feinkörnigen Behauptungen sind Snapshot-Tests nicht nützlich, um Regressionen abzufangen. Das liegt daran, dass Snapshot-Tests für die gesamte Vorlage gelten und Dinge außer Codeänderungen zu kleinen (oder not-so-small) Unterschieden in den Syntheseergebnissen führen können. Diese Änderungen wirken sich möglicherweise nicht einmal auf Ihre Bereitstellung aus, führen aber dennoch dazu, dass ein Snapshot-Test fehlschlägt.

Sie könnten beispielsweise ein CDK-Konstrukt aktualisieren, um eine neue bewährte Methode einzubeziehen, die zu Änderungen an den synthetisierten Ressourcen oder deren Organisation führen kann. Alternativ könnten Sie das CDK Toolkit auf eine Version aktualisieren, die zusätzliche Metadaten meldet. Änderungen an den Kontextwerten können sich auch auf die synthetisierte Vorlage auswirken.

Snapshot-Tests können jedoch beim Refactoring eine große Hilfe sein, solange Sie alle anderen Faktoren, die sich auf das synthetisierte Template auswirken könnten, konstant halten. Sie werden sofort wissen, ob eine von Ihnen vorgenommene Änderung die Vorlage unbeabsichtigt verändert hat. Wenn die Änderung beabsichtigt ist, akzeptieren Sie einfach die neue Vorlage als Grundlage.

Wenn wir zum Beispiel dieses `DeadLetterQueue` Konstrukt haben:

**Example**  

```
export class DeadLetterQueue extends sqs.Queue {
  public readonly messagesInQueueAlarm: cloudwatch.IAlarm;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Add the alarm
    this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', {
      alarmDescription: 'There are messages in the Dead Letter Queue',
      evaluationPeriods: 1,
      threshold: 1,
      metric: this.metricApproximateNumberOfMessagesVisible(),
    });
  }
}
```

```
class DeadLetterQueue extends sqs.Queue {

  constructor(scope, id) {
    super(scope, id);

    // Add the alarm
    this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', {
      alarmDescription: 'There are messages in the Dead Letter Queue',
      evaluationPeriods: 1,
      threshold: 1,
      metric: this.metricApproximateNumberOfMessagesVisible(),
    });
  }
}

module.exports = { DeadLetterQueue }
```

```
class DeadLetterQueue(sqs.Queue):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)

        self.messages_in_queue_alarm = cloudwatch.Alarm(
            self,
            "Alarm",
            alarm_description="There are messages in the Dead Letter Queue.",
            evaluation_periods=1,
            threshold=1,
            metric=self.metric_approximate_number_of_messages_visible(),
        )
```

```
public class DeadLetterQueue extends Queue {
    private final IAlarm messagesInQueueAlarm;

    public DeadLetterQueue(@NotNull Construct scope, @NotNull String id) {
        super(scope, id);

        this.messagesInQueueAlarm = Alarm.Builder.create(this, "Alarm")
                .alarmDescription("There are messages in the Dead Letter Queue.")
                .evaluationPeriods(1)
                .threshold(1)
                .metric(this.metricApproximateNumberOfMessagesVisible())
                .build();
    }

    public IAlarm getMessagesInQueueAlarm() {
        return messagesInQueueAlarm;
    }
}
```

```
namespace AwsCdkAssertionSamples
{
    public class DeadLetterQueue : Queue
    {
        public IAlarm messagesInQueueAlarm;

        public DeadLetterQueue(Construct scope, string id) : base(scope, id)
        {
            messagesInQueueAlarm = new Alarm(this, "Alarm", new AlarmProps
            {
                AlarmDescription = "There are messages in the Dead Letter Queue.",
                EvaluationPeriods = 1,
                Threshold = 1,
                Metric = this.MetricApproximateNumberOfMessagesVisible()
            });
        }
    }
}
```

Wir können es so testen:

**Example**  

```
import { Match, Template } from "aws-cdk-lib/assertions";
import * as cdk from "aws-cdk-lib";
import { DeadLetterQueue } from "../lib/dead-letter-queue";

describe("DeadLetterQueue", () => {
  test("matches the snapshot", () => {
    const stack = new cdk.Stack();
    new DeadLetterQueue(stack, "DeadLetterQueue");

    const template = Template.fromStack(stack);
    expect(template.toJSON()).toMatchSnapshot();
  });
});
```

```
const { Match, Template } = require("aws-cdk-lib/assertions");
const cdk = require("aws-cdk-lib");
const { DeadLetterQueue } = require("../lib/dead-letter-queue");

describe("DeadLetterQueue", () => {
  test("matches the snapshot", () => {
    const stack = new cdk.Stack();
    new DeadLetterQueue(stack, "DeadLetterQueue");

    const template = Template.fromStack(stack);
    expect(template.toJSON()).toMatchSnapshot();
  });
});
```

```
import aws_cdk_lib as cdk
from aws_cdk_lib.assertions import Match, Template

from app.dead_letter_queue import DeadLetterQueue

def snapshot_test():
    stack = cdk.Stack()
    DeadLetterQueue(stack, "DeadLetterQueue")

    template = Template.from_stack(stack)
    assert template.to_json() == snapshot
```

```
package software.amazon.samples.awscdkassertionssamples;

import org.junit.jupiter.api.Test;
import au.com.origin.snapshots.Expect;
import software.amazon.awscdk.assertions.Match;
import software.amazon.awscdk.assertions.Template;
import software.amazon.awscdk.Stack;

import java.util.Collections;
import java.util.Map;

public class DeadLetterQueueTest {
    @Test
    public void snapshotTest() {
        final Stack stack = new Stack();
        new DeadLetterQueue(stack, "DeadLetterQueue");

        final Template template = Template.fromStack(stack);
        expect.toMatchSnapshot(template.toJSON());
    }
}
```

```
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Amazon.CDK;
using Amazon.CDK.Assertions;
using AwsCdkAssertionSamples;

using ObjectDict = System.Collections.Generic.Dictionary<string, object>;
using StringDict = System.Collections.Generic.Dictionary<string, string>;

namespace TestProject1
{
    [TestClass]
    public class StateMachineStackTest

    [TestClass]
    public class DeadLetterQueueTest
    {
    [TestMethod]
        public void SnapshotTest()
        {
            var stack = new Stack();
            new DeadLetterQueue(stack, "DeadLetterQueue");

            var template = Template.FromStack(stack);

            return Verifier.Verify(template.ToJSON());
        }
    }
}
```

## Tipps für Tests
<a name="testing-tips"></a>

Denken Sie daran, dass Ihre Tests genauso lange gültig sind wie der Code, den sie testen, und sie werden genauso oft gelesen und geändert. Daher lohnt es sich, sich einen Moment Zeit zu nehmen, um zu überlegen, wie man sie am besten schreibt.

Kopieren Sie keine Setup-Zeilen oder allgemeine Behauptungen und fügen Sie sie nicht ein. Refaktorieren Sie diese Logik stattdessen in Fixtures oder Hilfsfunktionen. Verwenden Sie aussagekräftige Namen, die widerspiegeln, was jeder Test tatsächlich testet.

Versuchen Sie nicht, in einem Test zu viel zu tun. Vorzugsweise sollte ein Test nur ein Verhalten testen. Wenn Sie dieses Verhalten versehentlich brechen, sollte genau ein Test fehlschlagen, und der Name des Tests sollte Ihnen sagen, was fehlgeschlagen ist. Dies ist jedoch eher ein anzustrebendes Ideal. Manchmal schreiben Sie unweigerlich (oder versehentlich) Tests, die mehr als ein Verhalten testen. Snapshot-Tests sind aus Gründen, die wir bereits beschrieben haben, besonders anfällig für dieses Problem. Verwenden Sie sie daher sparsam.

# Lokales Testen und Erstellen von AWS CDK-Anwendungen mit der AWS SAM-CLI
<a name="testing-locally"></a>

Sie können die AWS SAM-CLI verwenden, um serverlose Anwendungen, die mit dem AWS Cloud Development Kit (AWS CDK) definiert wurden, lokal zu testen und zu erstellen. Da die AWS SAM-CLI innerhalb der AWS CDK-Projektstruktur funktioniert, können Sie die [AWS CDK-CLI-Referenz weiterhin zum Erstellen, Ändern und Bereitstellen Ihrer AWS CDK-Anwendungen](cli.md) verwenden.

Einzelheiten zur Verwendung von AWS SAM finden Sie unter [Erste Schritte mit AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) im * AWS Serverless Application* Model Developer Guide.

**Topics**
+ [Erste Schritte mit lokalen Tests](testing-locally-getting-started.md)
+ [Lokales Testen von AWS CDK-Anwendungen mit SAM AWS](testing-locally-with-sam-cli.md)
+ [AWS CDK-Anwendungen mit SAM erstellen AWS](testing-locally-build-with-sam-cli.md)

# Erste Schritte mit lokalen Tests
<a name="testing-locally-getting-started"></a>

In diesem Thema wird beschrieben, was Sie für die Verwendung der AWS SAM-CLI mit AWS CDK-Anwendungen benötigen, und es enthält Anweisungen zum Erstellen und lokalen Testen einer einfachen AWS CDK-Anwendung.

## Voraussetzungen
<a name="testing-locally-getting-started-prerequisites"></a>

Um lokal zu testen, müssen Sie die AWS SAM-CLI installieren. Installationsanweisungen finden [Sie unter AWS SAM-CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html) installieren.

## Eine AWS CDK-Anwendung erstellen und lokal testen
<a name="testing-locally-getting-started-tutorial"></a>

Um eine AWS CDK-Anwendung mit der AWS SAM-CLI lokal zu testen, benötigen Sie eine AWS CDK-Anwendung, die eine Lambda-Funktion enthält. Gehen Sie wie folgt vor, um eine grundlegende AWS CDK-Anwendung mit einer Lambda-Funktion zu erstellen. Weitere Informationen finden Sie unter [Creating a serverless application using the AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html) im * AWS Cloud Development Kit (AWS CDK)* Developer Guide.<a name="testing-locally-getting-started-tutorial-init"></a>

 **Schritt 1: Erstellen Sie eine CDK-Anwendung AWS **   
Initialisieren Sie für dieses Tutorial eine AWS CDK-Anwendung, die verwendet. TypeScript  
Befehl zum Ausführen:  

```
$ mkdir cdk-sam-example
$ cd cdk-sam-example
$ cdk init app --language typescript
```<a name="testing-locally-getting-started-tutorial-lambda"></a>

 **Schritt 2: Fügen Sie Ihrer Anwendung eine Lambda-Funktion hinzu**   
Ersetzen Sie den Code `lib/cdk-sam-example-stack.ts` durch folgenden Code:  

```
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkSamExampleStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.PYTHON_3_12,
      handler: 'app.lambda_handler',
      code: lambda.Code.fromAsset('./my_function'),
    });
  }
}
```<a name="testing-locally-getting-started-tutorial-code"></a>

 **Schritt 3: Fügen Sie Ihren Lambda-Funktionscode hinzu**   
Erstellen Sie ein Verzeichnis mit dem Namen `my_function`. Erstellen Sie in diesem Verzeichnis eine Datei namens `app.py`.  
Befehl zum Ausführen:  

**Example**  

```
$ mkdir my_function
$ cd my_function
$ touch app.py
```

```
$ mkdir my_function
$ cd my_function
$ type nul > app.py
```

```
$ mkdir my_function
$ cd my_function
$ New-Item -Path "app.py”
```
Fügen Sie folgenden Code zu hinz `app.py`:

```
def lambda_handler(event, context):
    return "Hello from SAM and the CDK!"
```<a name="testing-locally-getting-started-tutorial-function"></a>

 **Schritt 4: Testen Sie Ihre Lambda-Funktion**   
Sie können die AWS SAM-CLI verwenden, um lokal eine Lambda-Funktion aufzurufen, die Sie in einer AWS CDK-Anwendung definieren. Dazu benötigen Sie den Konstrukt-Identifier der Funktion und den Pfad zu Ihrer synthetisierten Vorlage. AWS CloudFormation   
Führen Sie den folgenden Befehl aus, um zum `lib` Verzeichnis zurückzukehren:  

```
$  cd ..
```
 **Befehl zum Ausführen:**   

```
$  cdk synth --no-staging
```

```
$  sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json
```
 **Beispielausgabe:**   

```
Invoking app.lambda_handler (python3.9)

START RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Version: $LATEST
"Hello from SAM and the CDK!"
END RequestId: 5434c093-7182-4012-9b06-635011cac4f2
REPORT RequestId: 5434c093-7182-4012-9b06-635011cac4f2	Init Duration: 0.32 ms	Duration: 177.47 ms	Billed Duration: 178 ms	Memory Size: 128 MB	Max Memory Used: 128 MB
```

# Lokales Testen von AWS CDK-Anwendungen mit SAM AWS
<a name="testing-locally-with-sam-cli"></a>

Sie können die AWS SAM-CLI verwenden, um Ihre AWS CDK-Anwendungen lokal zu testen, indem Sie die folgenden Befehle im Projektstammverzeichnis Ihrer AWS CDK-Anwendung ausführen:
+  ` [sam local invoke](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html) ` 
+  ` [sam local start-api](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html) ` 
+  ` [sam local start-lambda](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-lambda.html) ` 

Bevor Sie einen der `sam local` Befehle mit einer AWS CDK-Anwendung ausführen, müssen Sie ihn ausführen. `cdk synth`

Bei der Ausführung benötigen `sam local invoke` Sie den Konstrukt-Identifier der Funktion, den Sie aufrufen möchten, und den Pfad zu Ihrer synthetisierten AWS CloudFormation Vorlage. Wenn Ihre Anwendung verschachtelte Stacks verwendet, benötigen Sie zur Lösung von Namenskonflikten auch den Stacknamen, in dem die Funktion definiert ist.

 **Usage**   

```
# Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME
$  sam local invoke <OPTIONS> <STACK_NAME/FUNCTION_IDENTIFIER>

# Start all APIs declared in the AWS CDK application
$  sam local start-api -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS>

# Start a local endpoint that emulates AWS Lambda
$  sam local start-lambda -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS>
```

## Beispiel
<a name="testing-cdk-applications-examples"></a>

Betrachten Sie Stacks und Funktionen, die mit dem folgenden Beispiel deklariert wurden:

```
app = new HelloCdkStack(app, "HelloCdkStack",
   ...
)
class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    ...
    new lambda.Function(this, 'MyFunction', {
        ...
    });

    new HelloCdkNestedStack(this, 'HelloNestedStack' ,{
        ...
    });
  }
}

class HelloCdkNestedStack extends cdk.NestedStack {
  constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) {
    ...
    new lambda.Function(this, 'MyFunction', {
        ...
    });
    new lambda.Function(this, 'MyNestedFunction', {
        ...
    });
  }
}
```

Die folgenden Befehle rufen lokal die im obigen Beispiel definierten Lambda-Funktionen auf:

```
# Invoke MyFunction from the HelloCdkStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyFunction>
```

```
# Invoke MyNestedFunction from the HelloCdkNestedStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyNestedFunction>
```

```
# Invoke MyFunction from the HelloCdkNestedStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <HelloNestedStack/MyFunction>
```

# AWS CDK-Anwendungen mit SAM erstellen AWS
<a name="testing-locally-build-with-sam-cli"></a>

Die AWS SAM-CLI bietet Unterstützung für die Erstellung von Lambda-Funktionen und -Layern, die in Ihrer AWS CDK-Anwendung mit definiert sind. ` [sam build](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html) `

Bei Lambda-Funktionen, die Zip-Artefakte verwenden, führen Sie die `sam local` Befehle aus, `cdk synth` bevor Sie sie ausführen. `sam build`ist nicht erforderlich.

Wenn Ihre AWS CDK-Anwendung Funktionen mit dem Image-Typ verwendet, führen Sie sie aus `cdk synth` und führen Sie sie dann aus, `sam build` bevor Sie `sam local` Befehle ausführen. Wenn Sie ausführen`sam build`, erstellt AWS SAM keine Lambda-Funktionen oder -Layer, die laufzeitspezifische Konstrukte verwenden, z. B. ` [NodejsFunction](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) ` `sam build`[unterstützt keine gebündelten Ressourcen.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html)

## Beispiel
<a name="testing-locally-build-with-sam-cli-examples"></a>

Wenn Sie den folgenden Befehl im Stammverzeichnis des AWS CDK-Projekts ausführen, wird die Anwendung erstellt.

```
$ sam build -t <./cdk.out/CdkSamExampleStack.template.json>
```