

Este é o Guia do desenvolvedor do AWS CDK v2. O CDK v1 antigo entrou em manutenção em 1º de junho de 2022 e encerrou o suporte em 1º de junho de 2023.

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Teste AWS aplicativos CDK
<a name="testing"></a>

Com o AWS CDK, sua infraestrutura pode ser tão testável quanto qualquer outro código que você escreve. É possível testar na nuvem e localmente. Este tópico aborda como testar na nuvem. Para obter orientação sobre testes locais, consulte [Teste e crie aplicativos AWS CDK localmente com a CLI do AWS SAM](testing-locally.md). [A abordagem padrão para testar aplicativos AWS CDK usa o módulo de [asserções](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html) do AWS CDK e estruturas de teste populares, como [Jest para TypeScript e/ou JavaScript Pytest para Python](https://jestjs.io/).](https://docs.pytest.org/en/6.2.x/)

Há duas categorias de testes que você pode escrever para aplicativos AWS CDK.
+  **Asserções refinadas testam** aspectos específicos do AWS CloudFormation modelo gerado, como “esse recurso tem essa propriedade com esse valor”. Esses testes podem detectar regressões. Eles também são úteis quando você desenvolve novos atributos usando o desenvolvimento orientado a testes. (É possível escrever um teste primeiro e depois fazê-lo ser aprovado escrevendo uma implementação correta.) Afirmações minuciosas são os testes usados com mais frequência.
+  **Os testes instantâneos** testam o modelo sintetizado em relação a um AWS CloudFormation modelo de linha de base armazenado anteriormente. Os testes de snapshots possibilitam a você refatorar livremente, pois você pode ter certeza de que o código refatorado funciona exatamente da mesma forma que o original. Se as alterações foram intencionais, é possível aceitar uma nova linha de base para futuros testes. No entanto, as atualizações do CDK também podem fazer com que os modelos sintetizados sejam alterados, então você não pode confiar apenas em snapshots para garantir que sua implementação esteja correta.

**nota**  
Versões completas dos TypeScript aplicativos Python e Java usados como exemplos neste tópico estão [disponíveis](https://github.com/cdklabs/aws-cdk-testing-examples/) em. GitHub

## Introdução
<a name="testing-getting-started"></a>

Para ilustrar como escrever esses testes, criaremos uma pilha que contém uma máquina de estado AWS Step Functions e uma função Lambda AWS . A função do Lambda está inscrita em um tópico do Amazon SNS e simplesmente encaminha a mensagem para a máquina de estado.

Primeiro, crie um projeto vazio de aplicação do CDK usando o Kit de Ferramentas CDK e instalando as bibliotecas de que precisaremos. Os constructos que usaremos estão todos no pacote principal do CDK, que é uma dependência padrão em projetos criados com o Kit de Ferramentas CDK. Entretanto, você deve instalar sua estrutura de teste.

**Example**  

```
$ mkdir state-machine && cd state-machine
cdk init --language=typescript
npm install --save-dev jest @types/jest
```
Crie um diretório para seus testes.  

```
$ mkdir test
```
Edite os `package.json` dos projetos para dizer ao NPM como executar o Jest e para dizer ao Jest quais tipos de arquivos coletar. As mudanças necessárias são as seguintes.  
+ Adicione uma nova chave `test` à seção `scripts`
+ Adicione Jest e seus tipos à seção `devDependencies`
+ Adicione uma nova chave de nível superior `jest` com uma declaração `moduleFileExtensions`
Essas mudanças são mostradas no esboço a seguir. Coloque o novo texto onde indicado em `package.json`. Os espaços reservados “...” indicam partes existentes do arquivo que não devem ser alteradas.  

```
{
  ...
  "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
```
Crie um diretório para seus testes.  

```
$ mkdir test
```
Edite os `package.json` dos projetos para dizer ao NPM como executar o Jest e para dizer ao Jest quais tipos de arquivos coletar. As mudanças necessárias são as seguintes.  
+ Adicione uma nova chave `test` à seção `scripts`
+ Adicione Jest à seção `devDependencies`
+ Adicione uma nova chave de nível superior `jest` com uma declaração `moduleFileExtensions`
Essas mudanças são mostradas no esboço a seguir. Coloque o novo texto onde indicado em `package.json`. Os espaços reservados “...” indicam partes existentes do arquivo que não devem ser alteradas.  

```
{
  ...
  "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
```
Abra o projeto no Java IDE da sua preferência. (No Eclipse, use **Arquivo** > **Importar** > Projetos existentes do Maven.)

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=csharp
```
Abra a `src\StateMachine.sln` no Visual Studio.  
Clique com o botão direito do mouse na solução no Solution Explorer e escolha **Adicionar** > **Novo projeto**. Pesquise MSTest C\$1 e adicione um **projeto de MSTest teste** para C\$1. (O nome padrão `TestProject1` está bom.)  
Clique com o botão direito do mouse em `TestProject1` e escolha **Adicionar** > **Referência do projeto** e adicione o projeto `StateMachine` como referência.

## A pilha de exemplos
<a name="testing-app"></a>

Aqui está a pilha que será testada neste tópico. Como descrevemos anteriormente, ela contém uma função do Lambda e uma máquina de estados Step Functions e aceita um ou mais tópicos do Amazon SNS. A função do Lambda está inscrita nos tópicos do Amazon SNS e os encaminha para a máquina de estado.

Você não precisa fazer nada especial para tornar a aplicação testável. Na verdade, essa pilha do CDK não é diferente em nada importante das outras pilhas de exemplo neste Guia.

**Example**  
Coloque o seguinte código em `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);
    }
  }
}
```
Coloque o seguinte código em `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 }
```
Coloque o seguinte código em `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);
            }

        }
    }
}
```

Modificaremos o ponto de entrada principal da aplicação para que não instanciemos realmente nossa pilha. Não queremos implantá-la acidentalmente. Nossos testes criarão uma aplicação e uma instância da pilha para testes. Essa é uma tática útil quando combinada com o desenvolvimento orientado a testes: certifique-se de que a pilha seja aprovada em todos os testes antes de habilitar a implantação.

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

## A função do Lambda
<a name="testing-lambda"></a>

Nossa pilha de exemplos inclui uma função do Lambda que inicia nossa máquina de estado. Precisamos fornecer o código-fonte dessa função para que o CDK possa agrupá-la e implantá-la como parte da criação do recurso da função do Lambda.
+ Crie a pasta `start-state-machine` no diretório principal da aplicação.
+ Nessa pasta, crie pelo menos um arquivo. Por exemplo, você pode salvar o código a seguir no `start-state-machines/index.js`.

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

  No entanto, qualquer arquivo funcionará, já que não vamos realmente implantar a pilha.

## Execução de testes
<a name="testing-running-tests"></a>

Para referência, aqui estão os comandos que você usa para executar testes em seu aplicativo AWS CDK. Esses são os mesmos comandos que você usaria para executar os testes em qualquer projeto usando a mesma estrutura de testes. Para linguagens que exigem uma etapa de compilação, inclua-a para garantir que seus testes tenham sido compilados.

**Example**  

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

```
$ npm test
```

```
$ python -m pytest
```

```
$ mvn compile && mvn test
```
Crie sua solução (F6) para descobrir os testes e, em seguida, execute-os (**Teste** > **Executar todos os testes**). Para escolher quais testes executar, abra o Explorador de Testes (**Teste** > **Explorador de Testes**).  
Ou:  

```
$ dotnet test src
```

## Afirmações minuciosas
<a name="testing-fine-grained"></a>

A primeira etapa para testar uma pilha com afirmações refinadas é sintetizar a pilha, porque estamos escrevendo afirmações com base no modelo gerado. AWS CloudFormation 

Nosso `StateMachineStackStack` requer que passemos o tópico do Amazon SNS para ser encaminhado para a máquina estadual. Então, em nosso teste, criaremos uma pilha separada para conter o tópico.

Normalmente, ao escrever uma aplicação do CDK, é possível criar uma subclasse `Stack` e instanciar o tópico do Amazon SNS no construtor da pilha. Em nosso teste, instanciamos o `Stack` diretamente e, em seguida, passamos essa pilha como escopo, anexando-a à pilha `Topic`. Isso é funcionalmente equivalente e menos detalhado. Também ajuda a fazer com que as pilhas usadas somente em testes “pareçam diferentes” das pilhas que você pretende implantar.

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

Agora podemos afirmar que a função do Lambda e a assinatura do Amazon SNS foram criadas.

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

Nosso teste de função do Lambda afirma que duas propriedades específicas do recurso da função têm valores específicos. Por padrão, o `hasResourceProperties` método executa uma correspondência parcial nas propriedades do recurso, conforme indicado no modelo sintetizado CloudFormation . Esse teste exige que as propriedades fornecidas existam e tenham os valores especificados, mas o recurso também pode ter outras propriedades que não foram testadas.

Nossa afirmação do Amazon SNS afirma que o modelo sintetizado contém uma assinatura, mas não diz nada sobre a assinatura em si. Incluímos essa afirmação principalmente para ilustrar como afirmar a contagem de recursos. A `Template` classe oferece métodos mais específicos para escrever afirmações nas `Mapping` seções `Resources``Outputs`, e do CloudFormation modelo.<a name="testing-fine-grained-matchers"></a>

 **Combinadores**   
O comportamento padrão de correspondência parcial do `hasResourceProperties` pode ser alterado usando *combinadores* da classe ` [Match](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods) `.  
Os combinadores variam de tolerantes (`Match.anyValue`) a estritos (`Match.objectEquals`). Eles podem ser agrupados para aplicar diferentes métodos de correspondência a diferentes partes das propriedades do recurso. Usando `Match.objectEquals` e `Match.anyValue` juntos, por exemplo, podemos testar o perfil do IAM da máquina de estado de forma mais completa, sem exigir valores específicos para propriedades que possam mudar.  

**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" }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }));
```
Muitos CloudFormation recursos incluem objetos JSON serializados representados como strings. O combinador `Match.serializedJson()` pode ser usado para combinar propriedades dentro desse JSON.  
Por exemplo, as máquinas de estado do Step Functions são definidas usando uma string na [Amazon States Language](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) baseada em JSON. Usaremos `Match.serializedJson()` para garantir que nosso estado inicial seja a única etapa. Novamente, usaremos combinadores aninhados para aplicar diferentes tipos de correspondência a diferentes partes do objeto.  

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

 **Capturando**   
Geralmente, é útil testar propriedades para garantir que elas sigam formatos específicos ou tenham o mesmo valor de outra propriedade, sem precisar saber seus valores exatos com antecedência. O módulo `assertions` fornece esse recurso em sua classe ` [Capture](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html) `.  
Ao especificar uma instância `Capture` no lugar de um valor no `hasResourceProperties`, esse valor é retido no objeto `Capture`. O valor real capturado pode ser recuperado usando os métodos `as` do objeto, incluindo `asNumber()`, `asString()` e `asObject`, e passando por testes. Use `Capture` com um combinador para especificar a localização exata do valor a ser capturado nas propriedades do recurso, incluindo propriedades JSON serializadas.  
O exemplo a seguir testa para garantir que o estado inicial de nossa máquina de estado tenha um nome que comece com `Start`. Ele também testa se esse estado está presente na lista de estados da máquina.  

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

## Testes instantâneos
<a name="testing-snapshot"></a>

No *teste de instantâneo*, você compara todo o modelo sintetizado com um CloudFormation modelo de linha de base armazenado anteriormente (geralmente chamado de “mestre”). Ao contrário das afirmações refinadas, o teste instantâneo não é útil para capturar regressões. Isso ocorre porque o teste de instantâneo se aplica a todo o modelo, e coisas além das alterações no código podem causar pequenas (ou not-so-small) diferenças nos resultados da síntese. Essas alterações podem nem mesmo afetar sua implantação, mas ainda assim farão com que um teste instantâneo falhe.

Por exemplo, é possível atualizar um constructo do CDK para incorporar uma nova prática recomendada, que pode causar alterações nos recursos sintetizados ou na forma como eles são organizados. Como alternativa, é possível atualizar o Kit de Ferramentas CDK para uma versão que relata metadados adicionais. Alterações nos valores de contexto também podem afetar o modelo sintetizado.

No entanto, os testes instantâneos podem ser de grande ajuda na refatoração, desde que você mantenha constantes todos os outros fatores que possam afetar o modelo sintetizado. Você saberá imediatamente se uma alteração que você fez alterou involuntariamente o modelo. Se a alteração for intencional, basta aceitar o novo modelo como linha de base.

Por exemplo, se tivermos ess constructo `DeadLetterQueue`:

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

Podemos testá-lo assim:

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

## Dicas para testes
<a name="testing-tips"></a>

Lembre-se de que seus testes durarão tanto quanto o código testado e serão lidos e modificados com a mesma frequência. Portanto, vale a pena considerar a melhor forma de escrevê-las.

Não copie e cole linhas de configuração ou afirmações comuns. Em vez disso, refatore essa lógica em funções fixas ou auxiliares. Use bons nomes que reflitam o que cada teste realmente testa.

Não tente fazer muita coisa em um teste. De preferência, um teste deve testar apenas um comportamento. Se você quebrar acidentalmente esse comportamento, exatamente um teste falhará e o nome do teste deverá indicar o que falhou. No entanto, esse é mais um ideal a ser buscado; às vezes, você inevitavelmente (ou inadvertidamente) escreve testes que testam mais de um comportamento. Os testes instantâneos são, pelos motivos que já descrevemos, especialmente propensos a esse problema, portanto, use-os com moderação.

# Testes locais e compilação de aplicações do AWS CDK com a CLI do AWS SAM
<a name="testing-locally"></a>

É possível usar a CLI do AWS SAM para testar e criar localmente aplicações com tecnologia sem servidor definidas usando o kit de desenvolvimento em nuvem da AWS (CDK da AWS). Como a CLI do AWS SAM funciona dentro da estrutura de projeto do AWS CDK, você ainda pode usar a [Referência da CLI do AWS CDK](cli.md) para criar, modificar e implantar suas aplicações do AWS CDK.

Para obter detalhes sobre o uso do AWS SAM, consulte [Conceitos básicos do AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) no *Guia do desenvolvedor do modelo de aplicação com tecnologia sem servidor da AWS*.

**Topics**
+ [Conceitos básicos sobre testes locais](testing-locally-getting-started.md)
+ [Teste locais de aplicações do AWS CDK com o AWS SAM](testing-locally-with-sam-cli.md)
+ [Criação de aplicações do AWS CDK com o AWS SAM](testing-locally-build-with-sam-cli.md)

# Conceitos básicos sobre testes locais
<a name="testing-locally-getting-started"></a>

Este tópico descreve o que você precisa usar com a CLI do AWS SAM com aplicações do AWS CDK e fornece instruções para criar e testar localmente uma aplicação do AWS CDK.

## Pré-requisitos
<a name="testing-locally-getting-started-prerequisites"></a>

Para testar localmente, é necessário instalar a CLI do AWS SAM. Consulte [Instalação da CLI do AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html) para obter instruções de instalação.

## Criação e testes locais de uma aplicação do CDK da AWS
<a name="testing-locally-getting-started-tutorial"></a>

Para testar localmente uma aplicação do CDK da AWS usando a CLI do AWS SAM, é necessário ter uma aplicação do AWS CDK que contenha uma função do Lambda. Use as etapas a seguir para criar uma aplicação básica do CDK da AWS com uma função do Lambda. Para obter mais informações, consulte [Criação de uma aplicação com tecnologia sem servidor usando o CDK da AWS](https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html) no *Guia do desenvolvedor do kit de desenvolvimento em nuvem da AWS (CDK da AWS)*.<a name="testing-locally-getting-started-tutorial-init"></a>

 **Etapa 1: criar uma aplicação do CDK da AWS**   
Para este tutorial, inicialize uma aplicação do CDK da AWS que use TypeScript.  
Comando a ser executado:  

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

 **Etapa 2: adicionar uma função do Lambda à sua aplicação**   
Substitua o código em `lib/cdk-sam-example-stack.ts` pelo seguinte:  

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

 **Etapa 3: adicionar o código da função do Lambda**   
Crie um diretório chamado `my_function`. Nesse diretório, crie um arquivo chamado `app.py`.  
Comando a ser executado:  

**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”
```
Adicione o seguinte código a `app.py`:

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

 **Etapa 4: testar sua função do Lambda**   
É possível usar a CLI do AWS SAM para invocar localmente uma função do Lambda que você define em uma aplicação do AWS CDK. Para fazer isso, você precisa do identificador do constructo da função e do caminho para seu modelo sintetizado do AWS CloudFormation.  
Execute o comando a seguir para retornar ao diretório `lib`:  

```
$  cd ..
```
 **Comando a ser executado:**   

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

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

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

# Teste locais de aplicações do AWS CDK com o AWS SAM
<a name="testing-locally-with-sam-cli"></a>

É possível usar a CLI do AWS SAM para testar localmente suas aplicações do AWS CDK executando os comandos a seguir no diretório raiz do projeto da sua aplicação do AWS CDK:
+  ` [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) ` 

Antes de executar qualquer um dos comandos `sam local` com uma aplicação do AWS CDK, é necessário executar `cdk synth`.

Durante a execução de `sam local invoke` será necessário o identificador do constructo da função que você deseja invocar e do caminho para o modelo sintetizado do AWS CloudFormation. Se a sua aplicação usa pilhas aninhadas, para resolver conflitos de nomenclatura, você também precisará do nome da pilha em que a função está definida.

 **Uso**   

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

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

Considere pilhas e funções que são declaradas com o exemplo a seguir:

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

Os comandos a seguir invocam localmente as funções Lambda definidas no exemplo apresentado acima:

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

# Criação de aplicações do AWS CDK com o AWS SAM
<a name="testing-locally-build-with-sam-cli"></a>

A CLI do AWS SAM fornece suporte para criar funções e camadas do Lambda definidas na sua aplicação do AWS com ` [sam build](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html) `.

Para funções do Lambda que usem artefatos zip, execute `cdk synth` antes de executar os comandos `sam local`. `sam build` não é necessário.

Se a sua aplicação do AWS CDK usa funções com o tipo imagem, execute `cdk synth` e execute `sam build` antes de executar os comandos `sam local`. Quando você executa `sam build`, o AWS SAM não cria camadas ou funções do Lambda que usem constructos específicos de runtime, como, por exemplo, ` [NodejsFunction](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) `. O `sam build` não oferece suporte a [ativos agrupados](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html).

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

Executar a linha de comando a seguir no diretório raiz do AWS CDK projeto cria a aplicação.

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