<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gilson Silva</title>
    <description>The latest articles on Forem by Gilson Silva (@gilsonsilvati).</description>
    <link>https://forem.com/gilsonsilvati</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F887624%2F37bcd412-bf5d-49a9-800e-f54172c51a98.jpg</url>
      <title>Forem: Gilson Silva</title>
      <link>https://forem.com/gilsonsilvati</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gilsonsilvati"/>
    <language>en</language>
    <item>
      <title>Hot-Reload de Configurações de Portal Manager via /actuator/refresh no Spring Boot</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Sat, 18 Oct 2025 02:21:56 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/hot-reload-de-configuracoes-de-portal-manager-via-actuatorrefresh-no-spring-boot-2p14</link>
      <guid>https://forem.com/gilsonsilvati/hot-reload-de-configuracoes-de-portal-manager-via-actuatorrefresh-no-spring-boot-2p14</guid>
      <description>&lt;h2&gt;
  
  
  1. Como funciona o &lt;code&gt;/actuator/refresh&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;/actuator/refresh&lt;/code&gt; recarrega &lt;strong&gt;propriedades externas&lt;/strong&gt; de &lt;strong&gt;qualquer origem suportada pelo Spring Cloud&lt;/strong&gt; (não só &lt;code&gt;ConfigMap&lt;/code&gt;). Ou seja, se sua aplicação já busca configs de Portais Managers via PropertySource ou Config Server, o refresh pode funcionar sim para esses valores.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Fontes Externas Suportadas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spring Cloud Config Server&lt;/strong&gt; (centraliza configs em Git, S3, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Parameter Store&lt;/strong&gt; e &lt;strong&gt;AWS Secrets Manager&lt;/strong&gt; (via Spring Cloud AWS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HashiCorp Vault&lt;/strong&gt;, Consul, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Qualquer fonte implementada via &lt;code&gt;PropertySource&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Resumo:&lt;/strong&gt; Se o Portal Manager está integrado como um PropertySource do Spring Environment, o &lt;code&gt;/actuator/refresh&lt;/code&gt; pode recarregar esses valores.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Exemplo: AWS Parameter Store/Secrets Manager
&lt;/h2&gt;

&lt;h3&gt;
  
  
  a) Dependências
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Spring Boot Actuator e Cloud --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-actuator&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.awspring.cloud&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-starter-aws-parameter-store-config&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- ou --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.awspring.cloud&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-starter-aws-secrets-manager-config&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  b) Configuração do application.properties
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;management.endpoints.web.exposure.include&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;refresh,health,info&lt;/span&gt;
&lt;span class="py"&gt;spring.config.import&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;aws-parameterstore:/ # ou aws-secretsmanager:/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  c) Uso no código
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${minha.configuracao.sensivel}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;segredo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  d) Processo de atualização
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Altere o valor no Portal Manager&lt;/strong&gt; (ex: AWS Parameter Store).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chame o endpoint &lt;code&gt;/actuator/refresh&lt;/code&gt;&lt;/strong&gt; na aplicação.&lt;/li&gt;
&lt;li&gt;O valor é recarregado sem reiniciar o pod.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Observações Importantes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nem todos os beans/leitura de config reagem automaticamente ao refresh! Use &lt;code&gt;@RefreshScope&lt;/code&gt; nas classes/beans que dependem desses valores dinâmicos.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RefreshScope&lt;/span&gt;
&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MinhaController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${minha.configuracao.sensivel}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;segredo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;O &lt;code&gt;/actuator/refresh&lt;/code&gt; &lt;strong&gt;não recarrega configs de pods alheios&lt;/strong&gt;. Se você tem múltiplos pods, chame em todos (ou utilize Spring Cloud Bus para broadcast).&lt;/li&gt;
&lt;li&gt;Segurança: configure autenticação no endpoint &lt;code&gt;/actuator/refresh&lt;/code&gt;!&lt;/li&gt;
&lt;li&gt;Para AWS, use as bibliotecas do &lt;a href="https://github.com/awspring/spring-cloud-aws" rel="noopener noreferrer"&gt;Spring Cloud AWS&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Fluxo Resumido
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Integre o Portal Manager à sua aplicação Spring Boot via PropertySource.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;/actuator/refresh&lt;/code&gt; para recarregar configs em tempo real.&lt;/li&gt;
&lt;li&gt;Marque beans críticos como &lt;code&gt;@RefreshScope&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Você &lt;strong&gt;não precisa usar ConfigMap&lt;/strong&gt; para usar &lt;code&gt;/actuator/refresh&lt;/code&gt;! O segredo é garantir que seu Portal Manager está integrado como fonte de propriedades externas no Spring. Após alterar o valor no portal, basta acionar o refresh.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>microservices</category>
      <category>java</category>
      <category>devops</category>
    </item>
    <item>
      <title>Simulando um ambiente AWS com LocalStack</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Wed, 27 Nov 2024 01:03:52 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/simulando-um-ambiente-aws-com-localstack-5496</link>
      <guid>https://forem.com/gilsonsilvati/simulando-um-ambiente-aws-com-localstack-5496</guid>
      <description>&lt;p&gt;Se você está desenvolvendo aplicações que utilizam serviços da AWS, mas deseja evitar custos ou a complexidade de configurar recursos diretamente na nuvem, o &lt;strong&gt;LocalStack&lt;/strong&gt; é uma excelente solução. Ele permite simular um ambiente AWS localmente, oferecendo suporte a diversos serviços como S3, Lambda, DynamoDB, entre outros. Neste artigo, vamos explorar como configurar e usar o LocalStack para simular um ambiente AWS.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;O que é o LocalStack?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;O LocalStack é uma ferramenta que emula serviços da AWS em um ambiente local. Ele é amplamente utilizado para desenvolvimento e testes, permitindo que você crie, configure e interaja com recursos da AWS sem precisar de uma conta ou conexão com a nuvem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Passo a Passo para Configurar o LocalStack&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Pré-requisitos&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Antes de começar, certifique-se de ter os seguintes itens instalados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: O LocalStack é executado como um contêiner Docker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt;: Para interagir com os serviços simulados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LocalStack CLI&lt;/strong&gt; (opcional): Para gerenciar o LocalStack de forma mais eficiente.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Instalando o LocalStack&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Execute o seguinte comando para iniciar o LocalStack usando Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 &lt;span class="nt"&gt;-p&lt;/span&gt; 4571:4571 localstack/localstack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso iniciará o LocalStack e disponibilizará os serviços na porta 4566.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Configurando a AWS CLI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Configure a AWS CLI para apontar para o LocalStack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure

Access Key ID: &lt;span class="nb"&gt;test
&lt;/span&gt;Secret Access Key: &lt;span class="nb"&gt;test
&lt;/span&gt;Default region: us-east-1
Output format: json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, adicione o endpoint do LocalStack ao executar comandos. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;4. Criando Recursos Simulados&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Agora você pode criar e interagir com recursos simulados. Por exemplo, para criar um bucket S3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api create-bucket &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-local-bucket &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para listar os buckets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api list-buckets &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;5. Testando Funções Lambda&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Você também pode testar funções Lambda localmente. Primeiro, crie uma função Lambda simulada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--runtime&lt;/span&gt; python3.8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::123456789012:role/execution_role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--handler&lt;/span&gt; lambda_function.lambda_handler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--code&lt;/span&gt; &lt;span class="nv"&gt;S3Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-local-bucket,S3Key&lt;span class="o"&gt;=&lt;/span&gt;lambda-code.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Vantagens do LocalStack&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Custo Zero: Evita custos associados ao uso de serviços reais da AWS.&lt;/li&gt;
&lt;li&gt;Desenvolvimento Offline: Ideal para ambientes sem conexão com a internet.&lt;/li&gt;
&lt;li&gt;Rápida Configuração: Recursos podem ser criados e destruídos rapidamente.&lt;/li&gt;
&lt;li&gt;Integração com Ferramentas: Funciona bem com ferramentas como Terraform, AWS CLI e SDKs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Exemplo de Configuração Completa&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Aqui está um exemplo de configuração completa para simular um ambiente AWS com LocalStack:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Dockerfile&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;FROM public.ecr.aws/docker/library/node:21-slim&lt;/p&gt;

&lt;p&gt;RUN npm install -g npm@latest --loglevel=error&lt;br&gt;
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y curl &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*&lt;/p&gt;

&lt;p&gt;WORKDIR /usr/src/app&lt;br&gt;
COPY package*.json ./&lt;br&gt;
RUN npm install --loglevel=error&lt;br&gt;
COPY . .&lt;/p&gt;

&lt;p&gt;RUN NODE_OPTIONS=--openssl-legacy-provider REACT_APP_API_URL=&lt;a href="http://localhost:4566" rel="noopener noreferrer"&gt;http://localhost:4566&lt;/a&gt; SKIP_PREFLIGHT_CHECK=true npm run build --prefix client&lt;br&gt;
RUN mv client/build build&lt;br&gt;
RUN rm -rf client/*&lt;br&gt;
RUN mv build client/&lt;/p&gt;

&lt;p&gt;EXPOSE 8080&lt;br&gt;
CMD [ "npm", "start" ]&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Buildspec para Testes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;version: 0.2&lt;br&gt;
phases:&lt;br&gt;
  install:&lt;br&gt;
    commands:&lt;br&gt;
      - echo Installing Node 21 e npm.....&lt;br&gt;
      - curl -fsSL &lt;a href="https://rpm.nodesource.com/setup_21.x" rel="noopener noreferrer"&gt;https://rpm.nodesource.com/setup_21.x&lt;/a&gt; | sudo bash -&lt;br&gt;
      - sudo yum install -y nodejs&lt;br&gt;
  build:&lt;br&gt;
    commands:&lt;br&gt;
      - echo Build iniciado em &lt;code&gt;date&lt;/code&gt;&lt;br&gt;
      - npm install --loglevel=error&lt;br&gt;
      - REACT_APP_API_URL=&lt;a href="http://localhost:3001" rel="noopener noreferrer"&gt;http://localhost:3001&lt;/a&gt; SKIP_PREFLIGHT_CHECK=true npm run build --prefix client&lt;br&gt;
      - echo Rodando testes unitários.....&lt;br&gt;
      - npm test&lt;br&gt;
      - echo Testes unitários concluídos em &lt;code&gt;date&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusão&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;O LocalStack é uma ferramenta poderosa para simular serviços da AWS localmente, permitindo que desenvolvedores testem e validem suas aplicações sem depender de um ambiente real. Com ele, você pode economizar tempo e dinheiro enquanto mantém a flexibilidade de trabalhar com os serviços da AWS.&lt;/p&gt;

&lt;p&gt;Para mais informações, visite o site oficial do LocalStack: &lt;a href="https://www.localstack.cloud" rel="noopener noreferrer"&gt;https://www.localstack.cloud&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>📝 Logar de Maneira Sistemática: A Técnica dos 5 W</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Mon, 14 Oct 2024 23:13:59 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/logar-de-maneira-sistematica-a-tecnica-dos-5-w-49la</link>
      <guid>https://forem.com/gilsonsilvati/logar-de-maneira-sistematica-a-tecnica-dos-5-w-49la</guid>
      <description>&lt;p&gt;O &lt;strong&gt;log&lt;/strong&gt; é uma prática essencial no desenvolvimento de software, permitindo que desenvolvedores e equipes de operações monitorem, depurem e mantenham sistemas de forma eficiente. No entanto, para que os logs sejam realmente úteis, é importante que sejam feitos de maneira sistemática e organizada. Uma técnica eficaz para isso é o uso dos &lt;strong&gt;5 W: What, Why, Who, Where, When&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What (O quê?)&lt;br&gt;
O que está sendo logado?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O primeiro passo para um log eficiente é definir &lt;strong&gt;o que&lt;/strong&gt; será registrado. Isso pode incluir eventos importantes, erros, exceções, mudanças de estado, entre outros. O objetivo é capturar informações que ajudem a entender o comportamento do sistema.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "event": "user_login",
  "status": "success",
  "user_id": 12345
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Why (Por quê?)&lt;br&gt;
Por que esse evento é importante?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nem todos os eventos precisam ser logados. É importante entender &lt;strong&gt;por que&lt;/strong&gt; você está registrando determinado evento. Isso ajuda a evitar logs desnecessários e a focar em informações que realmente agregam valor, como erros críticos ou ações que afetam diretamente o funcionamento do sistema.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logar tentativas de login falhas pode ajudar a identificar possíveis ataques de força bruta.&lt;/li&gt;
&lt;li&gt;Logar mudanças de configuração pode ser útil para auditoria e rastreamento de problemas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Who (Quem?)&lt;br&gt;
Quem realizou a ação?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Identificar &lt;strong&gt;quem&lt;/strong&gt; realizou a ação é crucial para rastrear a origem de eventos. Isso pode ser um usuário, um serviço ou até mesmo um sistema externo. Incluir essa informação nos logs facilita a auditoria e a resolução de problemas.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "event": "file_upload",
  "user_id": 67890,
  "file_name": "document.pdf"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Where (Onde?)&lt;br&gt;
Onde o evento ocorreu?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Saber &lt;strong&gt;onde&lt;/strong&gt; o evento ocorreu é importante para identificar o contexto. Isso pode incluir o nome do servidor, o ambiente (produção, desenvolvimento), ou até mesmo a localização geográfica do usuário. Essa informação ajuda a isolar problemas específicos de um ambiente ou região.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "event": "api_request",
  "endpoint": "/api/v1/orders",
  "server": "prod-server-01"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. When (Quando?)&lt;br&gt;
Quando o evento aconteceu?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Registrar &lt;strong&gt;quando&lt;/strong&gt; o evento ocorreu é fundamental para correlacionar eventos e identificar padrões. A marcação de tempo (timestamp) deve ser precisa e, de preferência, no formato UTC para evitar confusões com fusos horários.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "event": "payment_processed",
  "timestamp": "2024-10-14T20:30:00Z"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utilizar a técnica dos &lt;strong&gt;5 W&lt;/strong&gt; para logar de maneira sistemática garante que seus logs sejam mais organizados, úteis e fáceis de interpretar. Isso facilita a identificação de problemas, a auditoria de ações e a manutenção do sistema como um todo. Lembre-se de sempre registrar &lt;strong&gt;o que&lt;/strong&gt; aconteceu, &lt;strong&gt;por que&lt;/strong&gt; é importante, &lt;strong&gt;quem&lt;/strong&gt; realizou a ação, &lt;strong&gt;onde&lt;/strong&gt; ocorreu e &lt;strong&gt;quando&lt;/strong&gt; aconteceu.&lt;/p&gt;

&lt;p&gt;Ao aplicar essa técnica, você estará criando logs mais eficientes e que realmente agregam valor ao seu processo de desenvolvimento e operação.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Testes Parametrizados com JUnit 5: Um Exemplo Prático 🚀</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Wed, 02 Oct 2024 15:38:18 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/testes-parametrizados-com-junit-5-um-exemplo-pratico-25lg</link>
      <guid>https://forem.com/gilsonsilvati/testes-parametrizados-com-junit-5-um-exemplo-pratico-25lg</guid>
      <description>&lt;p&gt;Os testes parametrizados são uma poderosa funcionalidade do JUnit 5 que permite executar o mesmo teste várias vezes com diferentes conjuntos de dados. Isso é especialmente útil quando você deseja testar um método com várias entradas e garantir que ele se comporte corretamente em todos os cenários.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos explorar como criar testes parametrizados usando o JUnit 5, com base no exemplo de um teste que verifica a criação de um objeto Planet com dados inválidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Antes, o que são Testes Parametrizados?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Testes parametrizados permitem que você execute o mesmo teste várias vezes com diferentes argumentos. Em vez de duplicar o código de teste para cada conjunto de dados, você pode fornecer uma lista de argumentos e o JUnit 5 executará o teste para cada um deles.&lt;/p&gt;

&lt;p&gt;No JUnit 5, a anotação &lt;em&gt;@ParameterizedTest&lt;/em&gt; é usada para indicar que um método de teste deve ser executado várias vezes com diferentes parâmetros. Esses parâmetros podem ser fornecidos de várias maneiras, como por meio de métodos estáticos (&lt;em&gt;@MethodSource&lt;/em&gt;), valores enumerados (&lt;em&gt;@EnumSource&lt;/em&gt;), ou até mesmo listas de valores (&lt;em&gt;@ValueSource&lt;/em&gt;). Em nosso exemplo, iremos utilizar &lt;strong&gt;@MethodSource&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo de Teste &lt;em&gt;SEM&lt;/em&gt; Parametrizado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2nwl1x60ylh2frmj1qd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2nwl1x60ylh2frmj1qd.png" alt="Image description" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo de Teste Parametrizado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vamos considerar o seguinte cenário: temos uma classe Planet que possui três atributos: name, climate e terrain. Queremos garantir que, ao tentar salvar um planeta com dados inválidos (como null ou strings vazias), uma exceção seja lançada.&lt;/p&gt;

&lt;p&gt;Aqui está o exemplo de um teste parametrizado que cobre esse cenário:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1aotl4q0ed6sdydnx82u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1aotl4q0ed6sdydnx82u.png" alt="Image description" width="772" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicação do Código:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;@ParameterizedTest:&lt;/strong&gt; Esta anotação indica que o método de teste será executado várias vezes, uma para cada conjunto de dados fornecido.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;@MethodSource("providesInvalidPlanets"):&lt;/strong&gt; Aqui, estamos usando um método estático chamado &lt;em&gt;providesInvalidPlanets&lt;/em&gt; para fornecer os argumentos para o teste. Esse método retorna um Stream de argumentos que serão passados para o teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;@DisplayName:&lt;/strong&gt; Esta anotação é usada para fornecer uma descrição legível para o teste, o que facilita a leitura dos relatórios de teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;assertThatThrownBy:&lt;/strong&gt; Este método, da biblioteca &lt;em&gt;AssertJ&lt;/em&gt;, é usado para verificar se uma exceção é lançada ao tentar salvar um planeta com dados inválidos. Estamos esperando que uma &lt;em&gt;RuntimeException&lt;/em&gt; seja lançada.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Método de Fornecimento de Dados&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O método &lt;em&gt;providesInvalidPlanets&lt;/em&gt; é responsável por fornecer os diferentes conjuntos de dados que serão usados no teste. Ele retorna um Stream de Arguments, onde cada Arguments.of representa um conjunto de dados (neste caso, um objeto Planet com valores inválidos).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7xaj64fisgm0zsxpy3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7xaj64fisgm0zsxpy3t.png" alt="Image description" width="739" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicação do Método:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stream.of:&lt;/strong&gt; Estamos criando um Stream de argumentos, onde cada argumento é um objeto Planet com diferentes combinações de valores inválidos (como null ou strings vazias).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arguments.of:&lt;/strong&gt; Cada chamada a Arguments.of cria um conjunto de argumentos que será passado para o teste. Neste caso, estamos criando planetas com combinações inválidas de name, climate e terrain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4loalydesrgzik1q4r1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4loalydesrgzik1q4r1.png" alt="Image description" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vantagens dos Testes Parametrizados&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redução de Código Duplicado:&lt;/strong&gt; Em vez de escrever vários métodos de teste para cada cenário, você pode usar um único método parametrizado, o que reduz a duplicação de código.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facilidade de Manutenção:&lt;/strong&gt; Se você precisar adicionar ou modificar um cenário de teste, basta alterar o método que fornece os dados, sem precisar duplicar o código de teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cobertura Abrangente:&lt;/strong&gt; Testes parametrizados permitem que você cubra uma ampla gama de cenários com facilidade, garantindo que seu código seja testado em diferentes condições.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os testes parametrizados são uma ferramenta poderosa no JUnit 5, permitindo que você execute o mesmo teste com diferentes conjuntos de dados de forma eficiente. No exemplo acima, mostramos como testar a criação de um objeto Planet com dados inválidos, garantindo que uma exceção seja lançada em todos os cenários.&lt;/p&gt;

&lt;p&gt;Essa abordagem não só melhora a cobertura de testes, mas também torna o código de teste mais limpo e fácil de manter. Se você ainda não está usando testes parametrizados em seus projetos, agora é um ótimo momento para começar!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Testes Subcutâneos - Comparação entre TestRestTemplate e WebTestClient em Testes de Integração 🧑‍💻</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Tue, 01 Oct 2024 22:39:25 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/testes-subcutaneos-comparacao-entre-testresttemplate-e-webtestclient-em-testes-de-integracao-2edg</link>
      <guid>https://forem.com/gilsonsilvati/testes-subcutaneos-comparacao-entre-testresttemplate-e-webtestclient-em-testes-de-integracao-2edg</guid>
      <description>&lt;p&gt;Ao realizar testes de integração em aplicações Spring Boot, duas abordagens populares para testar endpoints REST são o uso de &lt;em&gt;TestRestTemplate&lt;/em&gt; e &lt;em&gt;WebTestClient&lt;/em&gt;. Ambas as abordagens têm suas vantagens e desvantagens, e a escolha entre elas depende do contexto e das necessidades do projeto.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos comparar essas duas abordagens com base em dois exemplos de código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Testando com &lt;em&gt;TestRestTemplate&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
@DisplayName("Create Planet Return Created")
void createPlanet_ReturnCreated() {
    var sut = restTemplate.postForEntity(URL, PLANET_REQUEST_IT, PlanetResponse.class);

    assertThat(sut.getStatusCode()).isEqualTo(HttpStatus.CREATED);

    assertThat(sut.getBody()).isNotNull();

    assertThat(sut.getBody().name()).isEqualTo(PLANET_REQUEST_IT.name());
    assertThat(sut.getBody().terrain()).isEqualTo(PLANET_REQUEST_IT.terrain());
    assertThat(sut.getBody().climate()).isEqualTo(PLANET_REQUEST_IT.climate());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vantagens do TestRestTemplate:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicidade:&lt;/strong&gt; O &lt;em&gt;TestRestTemplate&lt;/em&gt; é fácil de usar e se integra bem com o Spring Boot. Ele é uma extensão do &lt;em&gt;RestTemplate&lt;/em&gt;, o que o torna familiar para desenvolvedores que já utilizam o &lt;em&gt;RestTemplate&lt;/em&gt; em suas aplicações.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes de Integração Completa:&lt;/strong&gt; O &lt;em&gt;TestRestTemplate&lt;/em&gt; é ideal para testes de integração completos, onde o servidor da aplicação é iniciado em uma porta real (ou aleatória) e as requisições são feitas como se fossem de um cliente externo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suporte a Vários Métodos HTTP:&lt;/strong&gt; Ele oferece suporte a todos os métodos HTTP (GET, POST, PUT, DELETE, etc.) e permite testar a API de forma semelhante a como um cliente real interagiria com ela.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens do TestRestTemplate:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Menos Flexível para Testes Reativos:&lt;/strong&gt; O &lt;em&gt;TestRestTemplate&lt;/em&gt; não é ideal para aplicações reativas, como aquelas que utilizam o Spring WebFlux. Ele foi projetado para o paradigma de programação imperativa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos Controle sobre a Resposta:&lt;/strong&gt; Embora seja possível verificar o status e o corpo da resposta, o &lt;em&gt;TestRestTemplate&lt;/em&gt; não oferece tantas opções de verificação e manipulação da resposta quanto o &lt;em&gt;WebTestClient&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Testando com WebTestClient&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
@DisplayName("Create Planet With WebTestClient Return Created")
void createPlanet_WithWebTestClient_ReturnsCreated() {
    var sut = webTestClient.post().uri(URL).bodyValue(PLANET_REQUEST_IT)
            .exchange().expectStatus().isCreated().expectBody(PlanetResponse.class)
            .returnResult().getResponseBody();

    assertThat(sut).isNotNull();
    assertThat(sut.name()).isEqualTo(PLANET_REQUEST_IT.name());
    assertThat(sut.climate()).isEqualTo(PLANET_REQUEST_IT.climate());
    assertThat(sut.terrain()).isEqualTo(PLANET_REQUEST_IT.terrain());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vantagens do WebTestClient:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Suporte a Aplicações Reativas:&lt;/strong&gt; O &lt;em&gt;WebTestClient&lt;/em&gt; foi projetado para trabalhar com o Spring WebFlux, o que o torna ideal para testar aplicações reativas. Ele suporta fluxos assíncronos e reativos, permitindo testar APIs que utilizam &lt;em&gt;Mono&lt;/em&gt; e &lt;em&gt;Flux&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maior Controle sobre a Resposta:&lt;/strong&gt; O &lt;em&gt;WebTestClient&lt;/em&gt; oferece uma API fluente que permite verificar o status da resposta, o corpo e até mesmo os headers de forma mais detalhada. Isso proporciona maior flexibilidade e controle sobre o que está sendo testado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes Sem Necessidade de Servidor Real:&lt;/strong&gt; O &lt;em&gt;WebTestClient&lt;/em&gt; pode ser usado para testar controladores diretamente, sem a necessidade de iniciar um servidor real. Isso pode acelerar os testes e torná-los mais eficientes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desvantagens do WebTestClient:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Curva de Aprendizado:&lt;/strong&gt; A API do &lt;em&gt;WebTestClient&lt;/em&gt; pode ser um pouco mais complexa para desenvolvedores que estão acostumados com o &lt;em&gt;RestTemplate&lt;/em&gt; ou &lt;em&gt;TestRestTemplate&lt;/em&gt;. A abordagem fluente pode exigir um pouco mais de tempo para se acostumar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos Adequado para Aplicações Imperativas:&lt;/strong&gt; Embora o &lt;em&gt;WebTestClient&lt;/em&gt; possa ser usado em aplicações não reativas, ele é mais adequado para o paradigma reativo. Para aplicações imperativas, o &lt;em&gt;TestRestTemplate&lt;/em&gt; pode ser uma escolha mais simples e direta.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comparação Direta&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;TestRestTemplate&lt;/th&gt;
&lt;th&gt;WebTestClient&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paradigma&lt;/td&gt;
&lt;td&gt;Imperativo&lt;/td&gt;
&lt;td&gt;Reativo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Facilidade de Uso&lt;/td&gt;
&lt;td&gt;Simples e familiar&lt;/td&gt;
&lt;td&gt;API fluente, mais flexível, mas mais complexa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suporte a WebFlux&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controle sobre a Resposta&lt;/td&gt;
&lt;td&gt;Básico&lt;/td&gt;
&lt;td&gt;Avançado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Necessidade de Servidor&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Velocidade dos Testes&lt;/td&gt;
&lt;td&gt;Mais lento&lt;/td&gt;
&lt;td&gt;Mais rápido&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A escolha entre &lt;em&gt;TestRestTemplate&lt;/em&gt; e &lt;em&gt;WebTestClient&lt;/em&gt; depende do tipo de aplicação que você está desenvolvendo e do nível de controle que você precisa nos seus testes. Se você está trabalhando com uma aplicação imperativa e precisa de testes simples e diretos, o &lt;em&gt;TestRestTemplate&lt;/em&gt; pode ser a melhor escolha. No entanto, se você está desenvolvendo uma aplicação reativa ou precisa de mais controle sobre as respostas HTTP, o &lt;em&gt;WebTestClient&lt;/em&gt; oferece uma abordagem mais poderosa e flexível.&lt;/p&gt;

&lt;p&gt;Ambas as ferramentas são úteis em diferentes contextos, e entender suas diferenças pode ajudar a escolher a abordagem certa para seus testes de integração.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Como Resolver Problemas com jsonPath("$") ao Usar Records no Java ❌😢</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Tue, 01 Oct 2024 13:53:15 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/como-resolver-problemas-com-jsonpath-ao-usar-records-no-java-1m6h</link>
      <guid>https://forem.com/gilsonsilvati/como-resolver-problemas-com-jsonpath-ao-usar-records-no-java-1m6h</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introdução&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Com a introdução dos Records no Java, muitos desenvolvedores estão aproveitando essa nova funcionalidade para criar classes imutáveis de maneira mais concisa. No entanto, ao testar APIs que retornam objetos JSON baseados em &lt;strong&gt;Records&lt;/strong&gt;, alguns desenvolvedores podem encontrar problemas ao usar o &lt;em&gt;jsonPath("$")&lt;/em&gt; no &lt;strong&gt;MockMvc&lt;/strong&gt; para verificar o conteúdo da resposta.&lt;/p&gt;

&lt;p&gt;Este artigo aborda o problema e apresenta uma solução simples usando o método &lt;em&gt;content().json()&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Problema&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ao usar &lt;strong&gt;MockMvc&lt;/strong&gt; para testar endpoints que retornam JSON, é comum usar o &lt;em&gt;jsonPath()&lt;/em&gt; para verificar o conteúdo da resposta. No entanto, ao trabalhar com &lt;strong&gt;Records&lt;/strong&gt;, você pode encontrar erros ao tentar usar &lt;em&gt;jsonPath("$")&lt;/em&gt; para verificar o tamanho ou o conteúdo da resposta JSON.&lt;/p&gt;

&lt;p&gt;Por exemplo, o seguinte código pode falhar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1evylfuh2k147ai34nli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1evylfuh2k147ai34nli.png" alt="Image description" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse erro ocorre porque o &lt;em&gt;jsonPath("$")&lt;/em&gt; pode não funcionar corretamente com a estrutura de &lt;strong&gt;Records&lt;/strong&gt;, especialmente ao tentar acessar o objeto raiz ou verificar o tamanho da resposta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução: Usando &lt;em&gt;content().json()&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uma solução simples e eficaz para esse problema é usar o método &lt;em&gt;content().json()&lt;/em&gt; do &lt;strong&gt;MockMvc&lt;/strong&gt;. Esse método permite verificar diretamente o conteúdo da resposta JSON, sem depender do &lt;em&gt;jsonPath()&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Aqui está um exemplo de como você pode usar &lt;em&gt;content().json()&lt;/em&gt; para verificar o tamanho da resposta JSON:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fow0ovmppbchb0e683a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fow0ovmppbchb0e683a.png" alt="Image description" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neste exemplo, o método &lt;em&gt;content().json()&lt;/em&gt; está verificando se a resposta JSON contém exatamente 3 objetos, sem precisar usar o &lt;em&gt;jsonPath("$")&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verificando o Conteúdo Exato&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Além de verificar o número de objetos, você pode usar &lt;em&gt;content().json()&lt;/em&gt; para verificar o conteúdo exato da resposta JSON. Por exemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fjdpig3dp07lgkutu6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fjdpig3dp07lgkutu6z.png" alt="Image description" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse código verifica se a resposta JSON contém exatamente os objetos esperados, com os campos &lt;em&gt;id&lt;/em&gt; e &lt;em&gt;name&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verificação Parcial&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se você não precisar verificar todos os campos, pode usar um JSON parcial:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndkwvwrvplv5ei99949k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndkwvwrvplv5ei99949k.png" alt="Image description" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O segundo parâmetro &lt;em&gt;false&lt;/em&gt; indica que campos extras no JSON de resposta serão ignorados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se você está enfrentando problemas ao usar &lt;em&gt;jsonPath("$")&lt;/em&gt; com &lt;strong&gt;Records&lt;/strong&gt;, a solução mais simples é usar o método &lt;em&gt;content().json()&lt;/em&gt; do &lt;strong&gt;MockMvc&lt;/strong&gt;. Ele permite verificar o conteúdo da resposta JSON de maneira direta e flexível, sem depender do &lt;em&gt;jsonPath()&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Essa abordagem é especialmente útil quando você precisa verificar o número de objetos no JSON ou o conteúdo exato da resposta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Espero que este artigo ajude a resolver os problemas que você está enfrentando ao testar APIs com Records no Java. Se você tiver mais dúvidas ou sugestões, fique à vontade para compartilhar!
&lt;/h2&gt;

</description>
      <category>java</category>
      <category>development</category>
      <category>developer</category>
      <category>test</category>
    </item>
    <item>
      <title>Utilizando ProblemDetail no Spring para tratamento de erros</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Mon, 30 Sep 2024 19:21:11 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/utilizando-problemdetail-no-spring-para-tratamento-de-erros-2mbi</link>
      <guid>https://forem.com/gilsonsilvati/utilizando-problemdetail-no-spring-para-tratamento-de-erros-2mbi</guid>
      <description>&lt;p&gt;O &lt;strong&gt;Spring Framework&lt;/strong&gt; oferece diversas formas de lidar com exceções e erros em APIs REST. Uma das abordagens mais modernas e recomendadas é o uso do ProblemDetail, que segue o padrão RFC 7807 para fornecer detalhes sobre problemas HTTP de forma estruturada e padronizada.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos explorar como utilizar o ProblemDetail no Spring para tratar exceções e retornar respostas de erro mais informativas e padronizadas para o cliente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que é o ProblemDetail?&lt;/strong&gt;&lt;br&gt;
O ProblemDetail é uma classe introduzida no Spring para facilitar o tratamento de erros em APIs REST. Ele permite que você forneça informações detalhadas sobre o erro ocorrido, como o status HTTP, uma mensagem descritiva, e até mesmo propriedades adicionais, como o timestamp do erro ou a categoria do problema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo de Uso&lt;/strong&gt;&lt;br&gt;
Vamos considerar um cenário onde estamos criando um planeta em uma API, mas o nome do planeta já existe no banco de dados. Nesse caso, uma exceção do tipo DataIntegrityViolationException será lançada, e queremos retornar uma resposta HTTP com status 409 Conflict e detalhes sobre o erro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teste de Integração&lt;/strong&gt;&lt;br&gt;
Primeiro, criamos um teste para garantir que, ao tentar criar um planeta com um nome já existente, a API retorne o status 409 Conflict.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
@DisplayName("Create Planet with existing name return conflict")
void createPlanet_WithExistingName_ReturnConflict() throws Exception {
    when(service.create(any(Planet.class))).thenThrow(DataIntegrityViolationException.class);

    mockMvc.perform(post("/planets")
                    .content(mapper.writeValueAsString(PLANET_REQUEST))
                    .contentType(APPLICATION_JSON))
            .andExpect(status().isConflict());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tratamento da Exceção com ProblemDetail&lt;/strong&gt;&lt;br&gt;
Para capturar a exceção &lt;strong&gt;DataIntegrityViolationException&lt;/strong&gt; e retornar uma resposta detalhada, utilizamos o @ExceptionHandler no Spring. O ProblemDetail nos permite fornecer informações adicionais sobre o erro, como o título, detalhes, e até mesmo propriedades personalizadas, como o StackTrace e o TimeStamp.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ExceptionHandler(DataIntegrityViolationException.class)
public ProblemDetail handleConflict(DataIntegrityViolationException ex) {
    var problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getLocalizedMessage());
    problemDetail.setTitle("Dado informado já existe");
    problemDetail.setDetail("É preciso informar um dado válido");
    problemDetail.setProperty("StackTrace", ex.getStackTrace());
    problemDetail.setProperty("Categoria", "API");
    problemDetail.setProperty("TimeStamp", Instant.now());

    return problemDetail;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicação do Código&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@ExceptionHandler(DataIntegrityViolationException.class):&lt;/strong&gt; Este método será chamado sempre que uma exceção do tipo DataIntegrityViolationException for lançada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getLocalizedMessage()):&lt;/strong&gt; Cria um objeto ProblemDetail com o status HTTP 409 Conflict e a mensagem de erro da exceção.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;setTitle e setDetail:&lt;/strong&gt; Definem o título e os detalhes do problema, que serão exibidos na resposta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;setProperty:&lt;/strong&gt; Adiciona propriedades personalizadas ao ProblemDetail, como o StackTrace, a categoria do erro e o timestamp do momento em que o erro ocorreu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resposta Esperada&lt;/strong&gt;&lt;br&gt;
Quando a exceção for lançada, a API retornará uma resposta no seguinte formato:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "about:blank",
  "title": "Dado informado já existe",
  "status": 409,
  "detail": "É preciso informar um dado válido",
  "instance": "/planets",
  "StackTrace": [...],
  "Categoria": "API",
  "TimeStamp": "2023-10-05T14:48:00Z"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;br&gt;
O uso do ProblemDetail no Spring permite que você forneça respostas de erro mais detalhadas e padronizadas, melhorando a experiência do consumidor da API e facilitando a depuração. Além disso, o ProblemDetail é altamente personalizável, permitindo que você adicione informações específicas sobre o erro, como o StackTrace e o TimeStamp.&lt;/p&gt;

</description>
      <category>springframework</category>
      <category>springboot</category>
      <category>api</category>
      <category>restfulapi</category>
    </item>
    <item>
      <title>Teste de Integração com Banco de Dados</title>
      <dc:creator>Gilson Silva</dc:creator>
      <pubDate>Fri, 27 Sep 2024 18:55:20 +0000</pubDate>
      <link>https://forem.com/gilsonsilvati/teste-de-integracao-com-banco-de-dados-47f6</link>
      <guid>https://forem.com/gilsonsilvati/teste-de-integracao-com-banco-de-dados-47f6</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Testes de integração são uma parte essencial da pirâmide de testes, pois garantem que diferentes partes do sistema funcionem corretamente quando integradas. No contexto de uma aplicação que utiliza um banco de dados, os testes de integração verificam se as operações de persistência de dados estão funcionando conforme o esperado. Neste artigo, vamos explorar um exemplo simples de teste de integração com o banco de dados usando a classe PlanetRepositoryTest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O que é o PlanetRepositoryTest?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A classe PlanetRepositoryTest é um teste de integração que verifica se o repositório de planetas (PlanetRepository) consegue salvar e recuperar corretamente um planeta no banco de dados. Esse teste utiliza o Spring Boot e a anotação &lt;strong&gt;@DataJpaTest&lt;/strong&gt;, que configura automaticamente um ambiente de teste com JPA e um banco de dados em memória.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estrutura do Teste&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aqui está a estrutura básica do teste de integração:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package br.com.starwars.domain;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;

import static br.com.starwars.common.PlanetConstants.PLANET;
import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
class PlanetRepositoryTest {

    @Autowired
    PlanetRepository repository;

    @Autowired
    TestEntityManager entityManager;

    @Test
    @DisplayName("Create Planet with valid data return Planet")
    void createPlanet_WithValidData_ReturnPlanet() {
        var savedPlanet = repository.save(PLANET);

        // sut: system under test (sistema em teste)
        var sut = entityManager.find(Planet.class, savedPlanet.getId());

        assertThat(sut).isNotNull();
        assertThat(sut.getName()).isEqualTo(PLANET.getName());
        assertThat(sut.getClimate()).isEqualTo(PLANET.getClimate());
        assertThat(sut.getTerrain()).isEqualTo(PLANET.getTerrain());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicação do Código&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Anotação @DataJpaTest:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A anotação @DataJpaTest é usada para configurar um ambiente de teste focado em JPA. Ela configura automaticamente um banco de dados em memória e escaneia apenas os componentes relacionados à persistência de dados, como repositórios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Injeção de Dependências:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O repositório PlanetRepository e o TestEntityManager são injetados automaticamente pelo Spring. O TestEntityManager é uma ferramenta útil para interagir diretamente com o banco de dados durante os testes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Teste createPlanet_WithValidData_ReturnPlanet():&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Este teste verifica se o repositório consegue salvar um planeta com dados válidos e, em seguida, recuperá-lo corretamente do banco de dados.&lt;/li&gt;
&lt;li&gt;O planeta é salvo usando o método save() do repositório.&lt;/li&gt;
&lt;li&gt;O TestEntityManager é usado para buscar o planeta salvo diretamente do banco de dados, garantindo que ele foi persistido corretamente.&lt;/li&gt;
&lt;li&gt;O teste então verifica se o planeta recuperado não é nulo e se seus atributos (nome, clima e terreno) correspondem aos valores esperados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Elevação da Pirâmide de Testes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A pirâmide de testes é um conceito que sugere que a maior parte dos testes deve ser composta por testes unitários, seguidos por testes de integração e, por fim, testes de ponta a ponta (end-to-end). Testes de integração, como o PlanetRepositoryTest, são mais lentos e complexos do que testes unitários, pois envolvem a interação com componentes externos, como o banco de dados. No entanto, eles são essenciais para garantir que as diferentes partes do sistema funcionem corretamente quando integradas.&lt;/p&gt;

&lt;p&gt;Neste exemplo, o teste de integração está focado na camada de persistência de dados, garantindo que o repositório funcione corretamente com o banco de dados. Ele complementa os testes unitários, que testam o comportamento isolado de classes e métodos, elevando a pirâmide de testes ao garantir que a integração entre o repositório e o banco de dados está funcionando conforme o esperado.&lt;/p&gt;

&lt;p&gt;Extra:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foki6ggx2fn5k0bhim419.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foki6ggx2fn5k0bhim419.png" alt="Image description" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O teste de integração PlanetRepositoryTest é uma parte importante do processo de desenvolvimento, pois garante que o repositório de planetas funcione corretamente com o banco de dados. Ao usar o Spring Boot e a anotação @DataJpaTest, podemos configurar um ambiente de teste eficiente e verificar se as operações de persistência estão funcionando conforme o esperado. Esse tipo de teste é essencial para garantir a qualidade e a confiabilidade da aplicação, especialmente em sistemas que dependem de interações com bancos de dados.&lt;/p&gt;

&lt;p&gt;#Desenvolvimento #Programação #Tecnologia #Inovação #Código #DevLife #StackSpot #Java #TestesAutomatizados #Desenvolvedor #TechLife #Software &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
