

Questa è la AWS CDK v2 Developer Guide. Il vecchio CDK v1 è entrato in manutenzione il 1° giugno 2022 e ha terminato il supporto il 1° giugno 2023.

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Test delle AWS applicazioni CDK
<a name="testing"></a>

Con il AWS CDK, la tua infrastruttura può essere testabile come qualsiasi altro codice che scrivi. Puoi eseguire il test nel cloud e localmente. Questo argomento spiega come eseguire test nel cloud. Per indicazioni sui test locali, consulta Testare [e creare applicazioni AWS CDK localmente con la CLI AWS SAM](testing-locally.md). [L'approccio standard per testare le app AWS CDK utilizza il modulo di [asserzioni](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html) del AWS CDK e i framework di test più diffusi come [Jest](https://jestjs.io/) for e/o Pytest for Python. TypeScript JavaScript ](https://docs.pytest.org/en/6.2.x/)

Esistono due categorie di test che puoi scrivere per le app CDK. AWS 
+  **Le asserzioni dettagliate** verificano aspetti specifici del AWS CloudFormation modello generato, ad esempio «questa risorsa ha questa proprietà con questo valore». Questi test possono rilevare regressioni. Sono utili anche quando sviluppi nuove funzionalità utilizzando lo sviluppo basato sui test. (Puoi prima scrivere un test, poi farlo passare scrivendo un'implementazione corretta.) Le asserzioni dettagliate sono i test più utilizzati.
+  **I test snapshot** testano il modello sintetizzato rispetto a un AWS CloudFormation modello di base precedentemente memorizzato. I test snapshot consentono di eseguire il refactoring liberamente, poiché si può essere certi che il codice refattorizzato funzioni esattamente allo stesso modo dell'originale. Se le modifiche sono state intenzionali, puoi accettare una nuova base per i test futuri. Tuttavia, gli aggiornamenti CDK possono anche causare la modifica dei modelli sintetizzati, quindi non potete affidarvi solo alle istantanee per assicurarvi che l'implementazione sia corretta.

**Nota**  
Le versioni complete delle TypeScript app Python e Java utilizzate come esempi in questo argomento sono [disponibili su](https://github.com/cdklabs/aws-cdk-testing-examples/). GitHub

## Nozioni di base
<a name="testing-getting-started"></a>

Per illustrare come scrivere questi test, creeremo uno stack che contiene una macchina a stati AWS Step Functions e una funzione Lambda AWS . La funzione Lambda è sottoscritta a un argomento di Amazon SNS e inoltra semplicemente il messaggio alla macchina a stati.

Innanzitutto, crea un progetto di applicazione CDK vuoto utilizzando CDK Toolkit e installando le librerie di cui avremo bisogno. I costrutti che useremo sono tutti contenuti nel pacchetto CDK principale, che è una dipendenza predefinita nei progetti creati con CDK Toolkit. Tuttavia, è necessario installare il framework di test.

**Example**  

```
$ mkdir state-machine && cd state-machine
cdk init --language=typescript
npm install --save-dev jest @types/jest
```
Crea una directory per i tuoi test.  

```
$ mkdir test
```
Modifica il progetto `package.json` per dire a NPM come eseguire Jest e per dire a Jest quali tipi di file raccogliere. Le modifiche necessarie sono le seguenti.  
+ Aggiungere una nuova `test` chiave alla `scripts` sezione
+ Aggiungi Jest e i suoi tipi alla sezione `devDependencies`
+ Aggiungi una nuova chiave `jest` di primo livello con una dichiarazione `moduleFileExtensions`
Queste modifiche sono illustrate nello schema seguente. Posiziona il nuovo testo dove indicato in`package.json`. I segnaposto «...» indicano parti esistenti del file che non devono essere modificate.  

```
{
  ...
  "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
```
Crea una cartella per i tuoi test.  

```
$ mkdir test
```
Modifica il progetto `package.json` per dire a NPM come eseguire Jest e per dire a Jest quali tipi di file raccogliere. Le modifiche necessarie sono le seguenti.  
+ Aggiungere una nuova `test` chiave alla `scripts` sezione
+ Aggiungi Jest alla sezione `devDependencies`
+ Aggiungi una nuova chiave `jest` di primo livello con una dichiarazione `moduleFileExtensions`
Queste modifiche sono illustrate nello schema seguente. Posiziona il nuovo testo dove indicato in`package.json`. I segnaposto «...» indicano parti esistenti del file che non devono essere modificate.  

```
{
  ...
  "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
```
Apri il progetto nel tuo IDE Java preferito. (In Eclipse, usa **File** > **Importa > Progetti** Maven esistenti.)

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=csharp
```
Apri `src\StateMachine.sln` in Visual Studio.  
Fai clic con il pulsante destro del mouse sulla soluzione in Solution Explorer e scegli **Aggiungi** > **Nuovo progetto**. Cerca MSTest C\$1 e aggiungi un **progetto di MSTest test** per C\$1. (Il nome predefinito `TestProject1`va bene.)  
Fate clic con il pulsante destro **del mouse `TestProject1` e **scegliete Aggiungi** > Riferimento** del progetto, quindi aggiungete il `StateMachine` progetto come riferimento.

## Lo stack di esempio
<a name="testing-app"></a>

Ecco lo stack che verrà testato in questo argomento. Come descritto in precedenza, contiene una funzione Lambda e una macchina a stati Step Functions e accetta uno o più argomenti di Amazon SNS. La funzione Lambda è sottoscritta agli argomenti di Amazon SNS e li inoltra alla macchina a stati.

Non devi fare nulla di speciale per rendere l'app testabile. In effetti, questo stack CDK non è diverso in alcun modo importante dagli altri stack di esempio in questa Guida.

**Example**  
Inserisci il seguente codice in: `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);
    }
  }
}
```
Inserisci il seguente codice in`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 }
```
Inserisci il seguente codice in`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);
            }

        }
    }
}
```

Modificheremo il punto di ingresso principale dell'app in modo da non creare effettivamente un'istanza del nostro stack. Non vogliamo distribuirlo accidentalmente. I nostri test creeranno un'app e un'istanza dello stack per i test. Questa è una tattica utile se combinata con lo sviluppo basato sui test: assicurati che lo stack superi tutti i test prima di abilitare l'implementazione.

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

## La funzione Lambda
<a name="testing-lambda"></a>

Il nostro stack di esempio include una funzione Lambda che avvia la nostra macchina a stati. Dobbiamo fornire il codice sorgente per questa funzione in modo che il CDK possa raggrupparla e distribuirla come parte della creazione della risorsa della funzione Lambda.
+ Crea la cartella `start-state-machine` nella directory principale dell'app.
+ In questa cartella, crea almeno un file. Ad esempio, è possibile salvare il codice seguente in`start-state-machines/index.js`.

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

  Tuttavia, qualsiasi file funzionerà, poiché in realtà non distribuiremo lo stack.

## Esecuzione di test.
<a name="testing-running-tests"></a>

A titolo di riferimento, ecco i comandi che utilizzate per eseguire i test nell'app AWS CDK. Questi sono gli stessi comandi che useresti per eseguire i test in qualsiasi progetto utilizzando lo stesso framework di test. Per le lingue che richiedono una fase di compilazione, includila per assicurarti che i test siano stati compilati.

**Example**  

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

```
$ npm test
```

```
$ python -m pytest
```

```
$ mvn compile && mvn test
```
Crea la tua soluzione (F6) per scoprire i test, quindi esegui i test (**Test** > **Esegui tutti i test**). Per scegliere quali test eseguire, apri Test Explorer (**Test > Test** **Explorer**).  
O:  

```
$ dotnet test src
```

## Asserzioni granulari
<a name="testing-fine-grained"></a>

Il primo passo per testare uno stack con asserzioni granulari è sintetizzare lo stack, perché stiamo scrivendo asserzioni sulla base del modello generato. AWS CloudFormation 

`StateMachineStackStack`Richiediamo che venga passato l'argomento Amazon SNS per essere inoltrato alla macchina a stati. Quindi, nel nostro test, creeremo uno stack separato per contenere l'argomento.

In genere, quando si scrive un'app CDK, è possibile creare sottoclassi `Stack` e istanziare l'argomento Amazon SNS nel costruttore dello stack. Nel nostro test, creiamo `Stack` direttamente un'istanza, quindi passiamo questo stack come ambito e lo colleghiamo allo stack. `Topic` Questo è funzionalmente equivalente e meno prolisso. Aiuta anche a far sì che gli stack utilizzati solo nei test «abbiano un aspetto diverso» dagli stack che intendi distribuire.

**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
        }
    }
}
```

Ora possiamo affermare che la funzione Lambda e l'abbonamento Amazon SNS sono stati creati.

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

Il nostro test funzionale Lambda afferma che due proprietà particolari della risorsa funzionale hanno valori specifici. Per impostazione predefinita, il `hasResourceProperties` metodo esegue una corrispondenza parziale sulle proprietà della risorsa come indicato nel modello sintetizzato CloudFormation . Questo test richiede che le proprietà fornite esistano e abbiano i valori specificati, ma la risorsa può avere anche altre proprietà, che non sono state testate.

La nostra affermazione di Amazon SNS afferma che il modello sintetizzato contiene un abbonamento, ma nulla sull'abbonamento stesso. Abbiamo incluso questa affermazione principalmente per illustrare come affermare il numero di risorse. La `Template` classe offre metodi più specifici per scrivere asserzioni rispetto alle `Mapping` sezioni `Resources``Outputs`, e del modello. CloudFormation <a name="testing-fine-grained-matchers"></a>

 **Matchers**   
Il comportamento di abbinamento parziale predefinito di `hasResourceProperties` può essere modificato utilizzando *i matcher* della ` [Match](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods) ` classe.  
I matcher vanno da lenient (`Match.anyValue`) a strict (). `Match.objectEquals` Possono essere annidati per applicare diversi metodi di corrispondenza a diverse parti delle proprietà della risorsa. Utilizzando `Match.objectEquals` e `Match.anyValue` insieme, ad esempio, possiamo testare in modo più completo il ruolo IAM della macchina a stati, senza richiedere valori specifici per le proprietà che potrebbero cambiare.  

**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" }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }));
```
Molte CloudFormation risorse includono oggetti JSON serializzati rappresentati come stringhe. Il `Match.serializedJson()` matcher può essere utilizzato per abbinare le proprietà all'interno di questo JSON.  
Ad esempio, le macchine a stati Step Functions vengono definite utilizzando una stringa in [Amazon States](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) Language basato su JSON. Lo useremo `Match.serializedJson()` per assicurarci che il nostro stato iniziale sia l'unico passaggio. Ancora una volta, useremo abbinatori annidati per applicare diversi tipi di corrispondenza a diverse parti dell'oggetto.  

**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>

 **Catturare**   
Spesso è utile testare le proprietà per assicurarsi che seguano formati specifici o abbiano lo stesso valore di un'altra proprietà, senza bisogno di conoscerne i valori esatti in anticipo. Il `assertions` modulo offre questa funzionalità nella sua ` [Capture](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html) ` classe.  
Specificando un'`Capture`istanza al posto di un valore in`hasResourceProperties`, tale valore viene mantenuto nell'`Capture`oggetto. Il valore effettivo acquisito può essere recuperato utilizzando i `as` metodi dell'oggetto, tra cui, e `asNumber()` `asString()``asObject`, e sottoposto a test. Da utilizzare `Capture` con un matcher per specificare la posizione esatta del valore da acquisire all'interno delle proprietà della risorsa, incluse le proprietà JSON serializzate.  
L'esempio seguente verifica che lo stato iniziale della nostra macchina a stati abbia un nome che inizia con. `Start` Verifica inoltre che questo stato sia presente nell'elenco degli stati della macchina.  

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

## Test istantanei
<a name="testing-snapshot"></a>

Nei *test delle istantanee*, si confronta l'intero modello sintetizzato con un CloudFormation modello di base precedentemente memorizzato (spesso chiamato «master»). A differenza delle asserzioni granulari, il test delle istantanee non è utile per rilevare le regressioni. Questo perché il test delle istantanee si applica all'intero modello e altre cose, oltre alle modifiche al codice, possono causare piccole (o) differenze nei risultati di sintesi. not-so-small Queste modifiche potrebbero non influire nemmeno sulla distribuzione, ma causeranno comunque il fallimento di un test di snapshot.

Ad esempio, è possibile aggiornare un costrutto CDK per incorporare una nuova best practice, che può causare modifiche alle risorse sintetizzate o al modo in cui sono organizzate. In alternativa, è possibile aggiornare CDK Toolkit a una versione che riporti metadati aggiuntivi. Le modifiche ai valori di contesto possono influire anche sul modello sintetizzato.

Tuttavia, i test istantanei possono essere di grande aiuto nel refactoring, purché si mantengano costanti tutti gli altri fattori che potrebbero influenzare il modello sintetizzato. Saprai immediatamente se una modifica apportata ha modificato involontariamente il modello. Se la modifica è intenzionale, è sufficiente accettare il nuovo modello come riferimento.

Ad esempio, se abbiamo questo `DeadLetterQueue` costrutto:

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

Possiamo testarlo in questo modo:

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

## Suggerimenti per i test
<a name="testing-tips"></a>

Ricorda che i tuoi test dureranno tanto quanto il codice che testano e verranno letti e modificati con la stessa frequenza. Pertanto, vale la pena dedicare un momento a considerare il modo migliore per scriverli.

Non copiate e incollate righe di configurazione o asserzioni comuni. Invece, rifattorizza questa logica in dispositivi o funzioni di supporto. Usa nomi validi che riflettano ciò che ogni test effettivamente verifica.

Non cercare di fare troppe cose in un solo test. Preferibilmente, un test dovrebbe testare uno e un solo comportamento. Se si interrompe accidentalmente tale comportamento, dovrebbe fallire esattamente un test e il nome del test dovrebbe indicare cosa non è riuscito. Tuttavia, questo è più un ideale da perseguire; a volte inevitabilmente (o inavvertitamente) si scrivono test che testano più di un comportamento. I test istantanei, per i motivi che abbiamo già descritto, sono particolarmente inclini a questo problema, quindi usateli con parsimonia.

# Testa e crea applicazioni AWS CDK localmente con la CLI AWS SAM
<a name="testing-locally"></a>

Puoi utilizzare la CLI AWS SAM per testare e creare localmente applicazioni serverless definite utilizzando il AWS Cloud Development Kit (AWS CDK). Poiché la CLI AWS SAM funziona all'interno della struttura del progetto AWS CDK, puoi comunque utilizzare il [riferimento CDK AWS CLI](cli.md) per creare, modificare e distribuire le tue applicazioni CDK. AWS 

*Per i dettagli sull'utilizzo di AWS SAM, consulta la [Guida introduttiva a SAM nella Serverless Application Model AWS Developer](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) Guide. AWS *

**Topics**
+ [Guida introduttiva ai test locali](testing-locally-getting-started.md)
+ [Test locali di applicazioni AWS CDK con SAM AWS](testing-locally-with-sam-cli.md)
+ [Creazione di applicazioni AWS CDK con SAM AWS](testing-locally-build-with-sam-cli.md)

# Guida introduttiva ai test locali
<a name="testing-locally-getting-started"></a>

Questo argomento descrive cosa è necessario per utilizzare la CLI AWS SAM con le applicazioni AWS CDK e fornisce istruzioni per creare e testare localmente una semplice AWS applicazione CDK.

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

Per eseguire il test localmente, è necessario installare AWS SAM CLI. Per istruzioni di installazione, vedere [Installazione della CLI AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html).

## Creare e testare localmente un'applicazione CDK AWS
<a name="testing-locally-getting-started-tutorial"></a>

Per testare localmente un'applicazione AWS CDK utilizzando la CLI AWS SAM, è necessario disporre di AWS un'applicazione CDK che contenga una funzione Lambda. Utilizza i seguenti passaggi per creare un'applicazione AWS CDK di base con una funzione Lambda. Per ulteriori informazioni, consulta [Creazione di un'applicazione serverless utilizzando AWS CDK nella Guida per gli](https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html) sviluppatori del * AWS Cloud Development Kit (AWS CDK)*.<a name="testing-locally-getting-started-tutorial-init"></a>

 **Fase 1: Creare un'applicazione CDK AWS **   
Per questo tutorial, inizializza un'applicazione AWS CDK che utilizza. TypeScript  
Comando da eseguire:  

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

 **Fase 2: Aggiungere una funzione Lambda all'applicazione**   
Sostituisci il codice `lib/cdk-sam-example-stack.ts` con quanto segue:  

```
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>

 **Fase 3: Aggiungere il codice della funzione Lambda**   
Crea una directory denominata `my_function`. Nella directory, creare un file denominato `app.py`.  
Comando da eseguire:  

**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”
```
Aggiungere il seguente codice a `app.py`:

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

 **Fase 4: Verifica la tua funzione Lambda**   
È possibile utilizzare la CLI AWS SAM per richiamare localmente una funzione Lambda definita in un'applicazione CDK. AWS A tale scopo, sono necessari l'identificatore del costrutto della funzione e il percorso del modello sintetizzato. AWS CloudFormation   
Eseguite il seguente comando per tornare alla directory: `lib`  

```
$  cd ..
```
 **Comando da eseguire:**   

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

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

```
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
```

# Test locali di applicazioni AWS CDK con SAM AWS
<a name="testing-locally-with-sam-cli"></a>

È possibile utilizzare la CLI AWS SAM per testare localmente le applicazioni AWS CDK eseguendo i seguenti comandi dalla directory principale del progetto dell'applicazione CDK: AWS 
+  ` [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) ` 

Prima di eseguire qualsiasi `sam local` comando con un'applicazione AWS CDK, è necessario eseguire. `cdk synth`

Durante l'esecuzione è `sam local invoke` necessario l'identificatore del costrutto della funzione che si desidera richiamare e il percorso del modello sintetizzato. AWS CloudFormation Se l'applicazione utilizza pile annidate, per risolvere i conflitti di denominazione, è necessario anche il nome dello stack in cui è definita la funzione.

 **Utilizzo**   

```
# 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>
```

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

Considerate gli stack e le funzioni dichiarati con l'esempio seguente:

```
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', {
        ...
    });
  }
}
```

I seguenti comandi richiamano localmente le funzioni Lambda definite nell'esempio presentato sopra:

```
# 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>
```

# Creazione di applicazioni AWS CDK con SAM AWS
<a name="testing-locally-build-with-sam-cli"></a>

La CLI AWS SAM fornisce supporto per la creazione di funzioni e livelli Lambda definiti nell'applicazione CDK con. AWS ` [sam build](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html) `

Per le funzioni Lambda che utilizzano elementi zip, esegui `cdk synth` prima di eseguire i comandi. `sam local` `sam build`non è obbligatorio.

Se l'applicazione AWS CDK utilizza funzioni con il tipo di immagine, eseguila `cdk synth` ed eseguila `sam build` prima di eseguire `sam local` i comandi. Durante l'esecuzione`sam build`, AWS SAM non crea funzioni o layer Lambda che utilizzano costrutti specifici del runtime, ad esempio. ` [NodejsFunction](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) ` `sam build`[non supporta risorse raggruppate.](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html)

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

L'esecuzione del comando seguente dalla directory principale del progetto AWS CDK crea l'applicazione.

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