<?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>DEV Community: Aleatório</title>
    <description>The latest articles on DEV Community by Aleatório (@lucasscharf).</description>
    <link>https://dev.to/lucasscharf</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%2F425569%2Fece85f88-38b4-4c37-882c-eca2b4b97f75.jpeg</url>
      <title>DEV Community: Aleatório</title>
      <link>https://dev.to/lucasscharf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasscharf"/>
    <language>en</language>
    <item>
      <title>Como usar Mockito no Quarkus (feat. jUnit)</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Tue, 25 Jan 2022 22:55:40 +0000</pubDate>
      <link>https://dev.to/lucasscharf/como-usar-mockito-no-quarkus-feat-junit-46h8</link>
      <guid>https://dev.to/lucasscharf/como-usar-mockito-no-quarkus-feat-junit-46h8</guid>
      <description>&lt;p&gt;Nos últimos tempos fiz dois posts topzeira, um falando sobre &lt;a href="https://dev.to/lucasscharf/aprendendo-sobre-testes-em-java-com-as-princesas-da-disney-1jk5"&gt;o que são testes&lt;/a&gt; e outro sobre como utilizar a lib do &lt;a href="https://www.testcontainers.org/" rel="noopener noreferrer"&gt;testcontainers&lt;/a&gt; para fazer testes de integração. No artigo de hoje, vamos utilizar a biblioteca &lt;a href="https://site.mockito.org/" rel="noopener noreferrer"&gt;Mockito&lt;/a&gt; para fazer os testes mockeados.&lt;/p&gt;

&lt;p&gt;Esse tutorial será dividido em três partes, no primeiro vamos trabalhar com a criação de mocks e controlar o comportamento deles; no segundo vamos utilizar a biblioteca para fazer o retorno dos objetos de forma condicional; e, por fim, vamos conseguir analisar bem o objeto que estamos recebendo para ver se está tudo correto. &lt;/p&gt;

&lt;p&gt;Para conseguir esse feito, vamos trazer o mestre do universo, o único que fica lindo de cabelo chanel e tanguinha, aquele que dá os melhores conselhos: He-man.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fiuln9wh3g9s7920t80ch.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fiuln9wh3g9s7920t80ch.jpg" alt="Image heman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  O que faremos?
&lt;/h1&gt;

&lt;p&gt;Nesse artigo vamos criar um o castelo de GraySkull onde as pessoas querem entrar. Esse castelo tem um porteiro que vai dizer se você entra na entrada VIP ou entrada normal.&lt;/p&gt;

&lt;p&gt;O castelo ficará com a seguinte cara.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.inject.Inject&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&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;CasteloDeGraySkull&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@Inject&lt;/span&gt;
  &lt;span class="nc"&gt;PortaoNormal&lt;/span&gt; &lt;span class="n"&gt;portaoNormal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@Inject&lt;/span&gt;
  &lt;span class="nc"&gt;PortaoVip&lt;/span&gt; &lt;span class="n"&gt;portaoVip&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@Inject&lt;/span&gt;
  &lt;span class="nc"&gt;Porteiro&lt;/span&gt; &lt;span class="n"&gt;porteiro&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;entrarNoCastelo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" está entrando no castelo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;porteiro&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;identificarSeÉVip&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;portaoVip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entrar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;portaoNormal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entrar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E cada portão tem a seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&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;PortaoNormal&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;entrar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" entrou pelo portão normal"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&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;PortaoVip&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;entrar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" entrou pelo portão VIP"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vem os problemas. Olha só o que aconteceu com o nosso porteiro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


&lt;span class="nd"&gt;@ApplicationScoped&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;Porteiro&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;identificarSeÉVip&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O porteiro faltou!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso mesmo, nós não temos a classe do porteiro. Isso pode acontecer por vários motivos. Seja por nós não sabermos as regras ainda ou por não termos implementado. Ou mesmo porque o porteiro depende de alguma aplicação externa que nem sempre vamos poder usar nos nossos testes.&lt;/p&gt;

&lt;p&gt;E é nesse ponto que a beleza do Quarkus e dos mocks entram. Nós não precisamos ter o objeto de verdade para seguirmos nossas implementações. Primeiro vamos adicionar a dependência para o Mockito. Fazemos isso adicionando o trecho abaixo entre as tags &lt;code&gt;&amp;lt;dependencies&amp;gt;&lt;/code&gt;do arquivo &lt;strong&gt;pom.xml&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&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.quarkus&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;quarkus-junit5&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&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;p&gt;Agora, vamos para a nossa classe de teste que será chamada de &lt;strong&gt;CasteloDeGraySkullTest&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;import javax.inject.Inject;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;

@QuarkusTest //0
public class CasteloDeGraySkullTest {
  @Inject
  CasteloDeGraySkull castelo;

  @InjectMock //1
  Porteiro porteiroMock;

  @Test
  public void testeEntrarNoNormal() {
    castelo.entrarNoCastelo("He-man"); //2
  }

  @Test
  public void testeEntrarNoVip() {
    Mockito.when(porteiroMock.identificarSeÉVip(Mockito.anyString())).thenReturn(true); //3
    castelo.entrarNoCastelo("She-ha");//4
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos analisar o nosso código.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0. A anotação @QuarkusTest indica que os testes  usarão a injeção de dependência do Quarkus.&lt;/li&gt;
&lt;li&gt;1. Quando usamos a anotação &lt;code&gt;@InjectMock&lt;/code&gt;, estamos dizendo que não é para injetarmos a classe verdadeira, porém uma versão mockada dela.&lt;/li&gt;
&lt;li&gt;2. Estamos fazendo o teste tendo o comportamento padrão do tipo &lt;strong&gt;boolean&lt;/strong&gt; que é retornar &lt;strong&gt;false&lt;/strong&gt;. Usando o comando &lt;code&gt;mvn test&lt;/code&gt;, veremos a seguinte saída:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;He-man está entrando no castelo
He-man entrou pelo portão normal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;3. Estamos mudando o comportamento do nosso mock. Estamos dizendo que para qualquer string que for passada (&lt;code&gt;Mockito.anyString()&lt;/code&gt;) para o método &lt;code&gt;porteiroMock.identificarSeÉVip()&lt;/code&gt; deve ser retornado o valor &lt;strong&gt;true&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;4. Temos o teste com o valor alterado, rodando o teste, teremos a seguinte saída:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;She-ha está entrando no castelo
She-ha entrou pelo portão VIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Tentei dividir ao máximo o conteúdo para que todo mundo possa acompanhar sem maiores problemas e entender bem o que houve. &lt;br&gt;
Mockito é uma biblioteca extremamente poderosa e auxilia bastante no desenvolvimento de testes rápidos e eficientes. Espero que todos gostem.&lt;/p&gt;

&lt;p&gt;Ah, e o código de hoje pode ser encontrado no &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/mockito" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;E no próximo post, teremos uma participação especial:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu9btf8038iv2xq9wc228.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu9btf8038iv2xq9wc228.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>braziliandevs</category>
      <category>testing</category>
      <category>quarkus</category>
    </item>
    <item>
      <title>Aprendendo sobre testes em Java com as princesas da Disney</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Mon, 25 Oct 2021 23:34:16 +0000</pubDate>
      <link>https://dev.to/lucasscharf/aprendendo-sobre-testes-em-java-com-as-princesas-da-disney-1jk5</link>
      <guid>https://dev.to/lucasscharf/aprendendo-sobre-testes-em-java-com-as-princesas-da-disney-1jk5</guid>
      <description>&lt;p&gt;&lt;em&gt;"Era uma vez, um jovem Aleatório que achou que existia muitos conteúdos legais sobre testes, mas resolveu adicionar seus dois centavos. O resto da história, vocês verão a seguir..."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O post de hoje será um dos mais legais e mais densos que eu já tive o prazer de fazer. Falaremos sobre um dos assuntos que eu mais gosto que são a̶s̶ ̶p̶r̶i̶n̶c̶e̶s̶a̶s̶ ̶d̶a̶ ̶D̶i̶s̶n̶e̶y̶ os testes. Juro que vou tentar ser o mais sucinto possível, mas conteúdo é tão legal que é capaz que eu me empolgue. Para conseguir me ajudar nessa tarefa, eu trouxe a minha princesa da Disney favorita:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxij38hkrxsv9wtrcbrb9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxij38hkrxsv9wtrcbrb9.jpg" alt="Image Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é um teste?
&lt;/h1&gt;

&lt;p&gt;No contexto de desenvolvimento, um teste de software consiste em um conjunto de ações que garantem que o software fará o que está se propondo a fazer. As ações realizadas variam de acordo com o projeto, a importância, o tempo disponível, complexidade, etc...&lt;/p&gt;

&lt;p&gt;Nesse ponto, trago um revelação: colocar o código em produção para ser utilizado pelos clientes já é um teste. Não é o melhor teste, tem vários riscos, mas acaba acontecendo ;/ &lt;br&gt;
Num mundo ideal, nosso sistema tem boa cobertura e conseguimos garantir que a nossa aplicação funcione e encontramos os casos de erro antes dos clientes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvnosasagpajd3carzgpp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvnosasagpajd3carzgpp.jpg" alt="Image jasmine meme"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h1&gt;
  
  
  O que testar?
&lt;/h1&gt;

&lt;p&gt;Esse ponto é polêmico e existem pessoas que defendem as mais diferentes opiniões. Alguns vão dizer que é para testar todos os casos possíveis, outros dirão que só precisa pegar os casos representativos, outros dirão que é necessário testar as interfaces, outros dirão que é preciso testar as aplicações usando sistemas reais outros dirão que os sistemas não precisam ser reais e por aí vai...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1e4mf8ejyl8o4zgd2ez4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1e4mf8ejyl8o4zgd2ez4.jpg" alt="Image Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como tudo na vida do dev, a resposta é: &lt;strong&gt;depende&lt;/strong&gt;. Depende do tempo, recursos, tamanho do time, conhecimento e importância do seu projeto. No &lt;strong&gt;meu caso&lt;/strong&gt;, eu prefiro testar o fluxo básico (também chamado de caminho feliz) com testes automatizados e alguns fluxos que eu acho que podem ocorrer erros. &lt;/p&gt;

&lt;p&gt;Conforme a aplicação é utilizada e os bugs vão sendo encontrados, então adiciono mais e mais testes automatizados que simulem esses erros e essa parte esteja coberta. Afinal, &lt;a href="https://dev.to/lucasscharf/usando-o-fault-tolerance-no-quarkus-porque-errar-e-umano-mas-tem-limites-4n2l"&gt;errar é umano, mas tem limites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sempre achei que essa abordagem é bom ponto de começo para os testes, trazendo o equilíbrio bom entre o que deve ser testado e os recursos disponíveis.&lt;/p&gt;
&lt;h1&gt;
  
  
  O que não testar
&lt;/h1&gt;

&lt;p&gt;Existe uma linha muito tênue entre você testar a sua aplicação e testar os frameworks que você está utilizando. O ideal é testar apenas o nosso código. E c̶o̶n̶f̶i̶a̶r̶ assumir que os frameworks estão bem testados e cobertos. &lt;/p&gt;

&lt;p&gt;Para exemplificar isso, vamos imaginar um método que recebe uma princesa, verifica se o nome está nulo e salva no banco.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;salvarPrincesa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Princesa&lt;/span&gt; &lt;span class="n"&gt;princesa&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;princesa&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNome&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Princesa com nome nulo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;princesaDao&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;salvar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;princesa&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Olhando esse método, você diria que um teste deve verificar se a princesa foi salva no banco?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkqbp4bfwni5hdncjgpdb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkqbp4bfwni5hdncjgpdb.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A resposta é &lt;strong&gt;NÃO&lt;/strong&gt;. Esse método não tem nenhuma relação com banco de dados. Ele lida com uma abstração (o &lt;a href="https://pt.wikipedia.org/wiki/Objeto_de_acesso_a_dados#:~:text=Objeto%20de%20acesso%20a%20dados%20(acr%C3%B4nimo%20do%20ingl%C3%AAs%20Data%20Access,por%20exemplo%20Java)%20e%20arquitetura" rel="noopener noreferrer"&gt;DAO&lt;/a&gt;). Logo, um teste deve verificar se o DAO foi chamado. Se o DAO vai realmente salvar no banco, vai colocar em memória ou vai dar uma maçã envenenada para que a princesa durma para todo o sempre, não é problema da nossa regra e negócio. Nossa regra testa apenas nome nulo e passa adiante.&lt;/p&gt;

&lt;p&gt;Caso seja necessário fazer um teste que verifica se o método salvar realmente salva no banco ou não, então esse teste deve ser feito em cima da classe PrincesaDao.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tipos de testes
&lt;/h1&gt;

&lt;p&gt;Da mesma forma que existem vários tipos de princesas, existem vários tipos de testes. E podemos classificar eles de diferentes formas. A lista abaixo traz algumas classificações possíveis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatizados
&lt;/h2&gt;

&lt;p&gt;Nesses testes, todo o processo de análise, execução dos testes e geração de relatórios é feito por um ou mais scripts diferentes. Isso permite que o mesmo teste possa ser repetido várias e várias vezes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manuais
&lt;/h2&gt;

&lt;p&gt;Por outro lado, os testes manuais são testes realizados com a interação humana. Nem tudo pode ser validado através de scripts ou o custo de automatizar pode não valer a pena. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fk2t464g079c38o2tifde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fk2t464g079c38o2tifde.png" alt="Image tiana com dinheiro"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testes funcionais
&lt;/h2&gt;

&lt;p&gt;Esses testes buscam garantir que o sistema faz o que ele se propõe a fazer. Existem várias formas de fazermos esses testes e por isso os testes funcionais são divididos de acordo com a granularidade. A divisão que eu apresento é um pouco diferente do que é visto na litaratura. Normalmente, os testes &lt;em&gt;mockeados&lt;/em&gt; ficam em algum limbo entre os testes unitários e os de integração.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teste unitário
&lt;/h3&gt;

&lt;p&gt;Esses testes são muito legais de fazer porque eles são rápidos, leves e permitem que você consiga cobrir um monte de situação diferente. &lt;br&gt;
Porém, eles duas pegadinhas. A) Muito código que você faz não pode ser testado de forma unitária. Pois ele acaba tendo dependências com objetos externos. B) Existem coisas que você não consegue testar com teste unitário.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teste &lt;em&gt;mockeado&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Uma saída para lidar com os objetos externos é criar um &lt;em&gt;mock&lt;/em&gt;. Um objeto de &lt;strong&gt;mentirinha&lt;/strong&gt; que vai reagir da forma que nós queremos e dando os retornos que nós esperamos. As duas principais bibliotecas de mock que nós temos é a &lt;a href="https://site.mockito.org/" rel="noopener noreferrer"&gt;Mockito&lt;/a&gt; e a &lt;a href="https://github.com/powermock/powermock" rel="noopener noreferrer"&gt;Powermock&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Teste de integração
&lt;/h3&gt;

&lt;p&gt;Ao invés de usar um &lt;em&gt;mock&lt;/em&gt; para simular os objetos e ambientes externos, por que não usar algo de verdade? &lt;br&gt;
Seguindo a linha dos &lt;a href="https://12factor.net/pt_br/" rel="noopener noreferrer"&gt;12 fatores para desenvolvimento de software&lt;/a&gt;, os ambientes de devsenvolvimento e produção devem ser semelhantes. Logo, se a aplicação funcionará usando um banco de dados de verdade, vamos testar usando um banco de dados de verdade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teste ponta-à-ponta
&lt;/h3&gt;

&lt;p&gt;Esse é o suprassumo dos testes. Muitas pessoas são contra fazê-los porque eles são caros ou difíceis de serem realizados. Mas esses testes são os mais próximos da realidade. &lt;br&gt;
Nesse tipo de teste levantamentos todos os sistemas e dependências de verdade. Buscando chegar o mais próximo do que é feito no mundo real. &lt;/p&gt;

&lt;h2&gt;
  
  
  Teste caixa preta
&lt;/h2&gt;

&lt;p&gt;Essa nomenclatura serve mais para dizer que o teste é criado/planejado/executado sem saber as estruturas internas da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teste caixa branca
&lt;/h2&gt;

&lt;p&gt;Ao contrário dos testes caixa-preta, nos testes caixa-branca, os testes são criados já tendo em mente as estruturas internas da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teste de performance
&lt;/h2&gt;

&lt;p&gt;Esses testes buscam descobrir como é o desempenho do sistema em diferentes cenários. &lt;/p&gt;

&lt;h3&gt;
  
  
  Teste de carga
&lt;/h3&gt;

&lt;p&gt;Visa medir os tempos de resposta e vazões do sistema em diferentes cargas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teste de &lt;em&gt;stress&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Semelhante a teste anterior em termos de execução, mas totalmente em sua filosofia. Esse teste busca tanto descobrir quais são os limites da aplicação bem como o comportamento do sistema atuando no limite. &lt;/p&gt;

&lt;h2&gt;
  
  
  Teste de regressão
&lt;/h2&gt;

&lt;p&gt;Consiste em executar todos testes funcionais criados (ou demais testes quando relevante) para garantir que novas mudanças e alterações não introduzam novos erros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teste de segurança
&lt;/h2&gt;

&lt;p&gt;Também conhecido com &lt;a href="https://pt.wikipedia.org/wiki/Teste_de_intrus%C3%A3o" rel="noopener noreferrer"&gt;teste de penetração&lt;/a&gt;. Geralmente é feito por alguma empresa externa e visa encontrar falhas de segurança tanto no código quanto nos processos executados pela aplicação/empresa. &lt;/p&gt;

&lt;h2&gt;
  
  
  Teste de usabilidade
&lt;/h2&gt;

&lt;p&gt;Mais focado para aplicações que tem telas, esse tipo de teste consiste em navegar pelas telas feitas (ou por ideias de telas) para verificar se elas atenderão o usuário. &lt;/p&gt;

&lt;h2&gt;
  
  
  Teste de aceitação
&lt;/h2&gt;

&lt;p&gt;O sonho de consumo de todo o software. Os testes de aceitação vão dizer se o software está pronto ou não para receber o aceite do cliente. &lt;/p&gt;

&lt;h1&gt;
  
  
  Por que testar?
&lt;/h1&gt;

&lt;p&gt;Qualidade. Fazer testes é o que permite dizer que nossa aplicação funciona ou não. Como vocês viram no outro tópico, existem várias formas de fazer isso.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dicas gerais de como testar
&lt;/h1&gt;

&lt;p&gt;Caso você seja a Aurora ou Cinderella, você tem uma fada madrinha que te dará uma mão para resolver os problemas. Caso você não seja, você precisa se ajudar. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzvg1cf4x7m9i280of4dr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzvg1cf4x7m9i280of4dr.jpg" alt="Image aleatório de fado madrinho"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Separei algumas dicas para trabalhar tanto em ferramentas que podem te ajudar a fazerem bonito nesse baile dos testes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Faça que os testes rodem de forma rápida
&lt;/h2&gt;

&lt;p&gt;Desenvolver é algo estressante então as coisas precisam ser rápidas. Se cada vez que você precisar rodar os testes, você levar 10 minutos esperando, a tendência é que você pare de testar. &lt;br&gt;
Parando de testar, as coisas começam a dar ruim. Dando ruim, os prazos vão se apertar. Apertando os prazos, você vai tirar  o que for menos necessárias para o sistema ir pra produção. Tirando o menos necessário, você tirará os testes e as coisas vão ficando &lt;strong&gt;pior&lt;/strong&gt;.  Então é MUITO importante que você consiga fazer com que os testes rodem rápido. &lt;/p&gt;

&lt;h2&gt;
  
  
  Escreva um código que facilite os testes
&lt;/h2&gt;

&lt;p&gt;Se o seu código não for pensado para testes, quando você for escrevê-los você provavelmente terá dificuldades. Tendo dificuldade para testar, você vai parar de testar. Parando de testar, as coisas começam a dar ruim...&lt;/p&gt;

&lt;h3&gt;
  
  
  Evite o uso de &lt;em&gt;static&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Métodos estáticos como &lt;code&gt;LocalDate.now()&lt;/code&gt; ou &lt;code&gt;Objects.isNull()&lt;/code&gt; não podem ser &lt;em&gt;mockeados&lt;/em&gt; facilmente. Então, se você precisa testar com algum comportamento específico, fica complicado. &lt;/p&gt;

&lt;p&gt;Sempre que aparecer um método estático, pense se isso pode afetar os testes. Caso afete, utilize um objeto para encapsular esse método.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saiba o porque do teste estar ali
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fl38ncuembd1qv7t0v6jq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fl38ncuembd1qv7t0v6jq.gif" alt="Image ariel pentendo o cabelo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Muitas vezes nós fazemos as coisas sem saber bem o que estamos fazendo ou o porquê das coisas. Com isso, nós podemos testar umas 10 vezes a mesma lógica e deixar de testar algo importante. Então, antes de escrever qualquer coisa crie algum tipo de "plano" onde você define o que você quer testar e o motivo desse teste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utilize ferramentas para verificar a cobertura de testes
&lt;/h2&gt;

&lt;p&gt;Se nós não conseguimos medir, nós nem podemos dizer se estamos fazendo um bom trabalho (provavelmente, nosso trabalho está ruim).&lt;br&gt;
O &lt;a href="https://www.eclemma.org/jacoco/" rel="noopener noreferrer"&gt;JaCoCo&lt;/a&gt; é uma ferramenta ótima para dizer como está nossa cobertura. O que estamos esquecendo e o que precisamos melhorar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas não se prenda muito a isso
&lt;/h2&gt;

&lt;p&gt;É importante ter uma boa cobertura de teste. Particularmente, eu acho que 80% para um projeto maduro é um bom número. Existem coisas que simplesmente são caras demais para serem testadas, ou que só não tem motivo para testar. &lt;br&gt;
Além disso, buscar os 100% pode dar a falsa sensação de que você tem todos os casos possíveis mapeados e que nunca vai acontecer um erro. Spoiler: a menos que o seu nome seja Mulan e você esteja lutando contra os Hunos, você vai errar. &lt;br&gt;
&lt;a href="https://media.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%2F058lsrdv1uh6ptxmhya3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F058lsrdv1uh6ptxmhya3.png" alt="Image mulan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Esse post foi mais teórico. Nos próximos, vamos ver como fazer testes unitários, mockeados e de integração. Tudo isso trabalhando com Quarkus. Aguardem a continuação /o/&lt;/p&gt;

</description>
      <category>testing</category>
      <category>braziliandevs</category>
      <category>java</category>
    </item>
    <item>
      <title>Usando o fault tolerance no Quarkus, porque errar é umano, mas tem limites!</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Tue, 18 May 2021 23:46:58 +0000</pubDate>
      <link>https://dev.to/lucasscharf/usando-o-fault-tolerance-no-quarkus-porque-errar-e-umano-mas-tem-limites-4n2l</link>
      <guid>https://dev.to/lucasscharf/usando-o-fault-tolerance-no-quarkus-porque-errar-e-umano-mas-tem-limites-4n2l</guid>
      <description>&lt;p&gt;Encare os fatos, em algum momento a sua aplicação vai falhar. &lt;/p&gt;

&lt;p&gt;Porém, não é porque erramos que vamos precisamos chorando em posição fetal por termos falhando. Nós podemos nos recuperar facilmente e o Quarkus nos auxilia nesse processo. &lt;/p&gt;

&lt;p&gt;Então, se você souber como errar ou como se recuperar desse erro, a sua aplicação ficará bem. O Quarkus traz uma extensão batuta para lidar com essas situações: a &lt;em&gt;fault tolerance&lt;/em&gt;. No post de hoje, vamos conhecer essa extensão.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que faremos
&lt;/h1&gt;

&lt;p&gt;Vamos construir um microsserviço com alguns endpoints REST. Esses endpoints vão falhar de diferentes formas. Após isso, vamos implementar soluções simples e elegantes para contornar essas falhas.&lt;/p&gt;

&lt;h1&gt;
  
  
  É hora da ação
&lt;/h1&gt;

&lt;p&gt;Vamos começar indo no &lt;a href="https://code.quarkus.io/" rel="noopener noreferrer"&gt;code.quarkus.io&lt;/a&gt;, selecionar a extensão &lt;strong&gt;SmallRye Fault Tolerance&lt;/strong&gt;, mandar baixar com código de exemplo. Isso criará um serviço rest bem simples que retornará uma String de &lt;strong&gt;hello&lt;/strong&gt;. Vamos mudar um pouco a classe criada e criando alguns endpoints que simularão diferentes situações de erro e que nós iremos tratar. O código com essas situações ficará assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.acme&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.ws.rs.GET&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.ws.rs.Path&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;)&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;ExampleResource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@GET&lt;/span&gt;
  &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/timeout"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;helloComTimeout&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;tentativaComSleep&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;tentativaComSleep&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5_000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"hello com timeout"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@GET&lt;/span&gt;
  &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/retries"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;helloComRetry&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tentativaComRetentativas&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"hello com retry"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;tentativaComRetentativas&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;contador&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tentativa número: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" às "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@GET&lt;/span&gt;
  &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/fallback"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;helloComFallback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;tentativaComFallback&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;tentativaComFallback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criamos 3 endpoints. O primeiro responde, porém demora algum tempo para isso, o segundo e o terceiro não conseguem responder por causa de alguma exceção. Agora nós vamos contornar essas situações com o suporte da nossa biblioteca de tolerância a falhas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeout
&lt;/h2&gt;

&lt;p&gt;A condição de timeout é ativada quando o sistema demora tempo demais para responder. &lt;br&gt;
O contorno dela se baseia em criar uma &lt;em&gt;thread&lt;/em&gt; para ficar monitorando o tempo de início de execução e estourar uma exception caso esse tempo seja excedido. &lt;/p&gt;

&lt;p&gt;Porém, não precisamos escrever muito para ter tudo isso.&lt;br&gt;
Basta adicionar a anotação &lt;strong&gt;@Timeout&lt;/strong&gt; com o tempo limite que nós queremos. Caso o método não complete a operação a tempo, será lançada uma exceção do tipo &lt;strong&gt;TimeoutException.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Depois disso é só será tratar essa exceção com o comportamento que desejado. Dessa forma, o Quarkus controla toda essa parte de controle de tempo, &lt;em&gt;threads&lt;/em&gt;, etc...&lt;/p&gt;

&lt;p&gt;Alterando o código da requisição, ficará assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
  &lt;span class="nd"&gt;@GET&lt;/span&gt;
  &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/timeout"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;helloComTimeout&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;tentativaComSleep&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TimeoutException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Tentativa com timeout tratado, seu serviço responderá rápido"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Timeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&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="nf"&gt;tentativaComSleep&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5_000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"hello com timeout"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nosso código passará a responder mais rápido (ainda que seja com um comportamento diferente), fazendo com que a experiência do usuário seja mais suave.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9lqmxh2v9s4ns38529f0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9lqmxh2v9s4ns38529f0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Retentativas
&lt;/h2&gt;

&lt;p&gt;Às vezes, o problema pode não ser que o serviço demore demais para responder, talvez o problema pode ser resolvido se nós tentarmos novamente algum tempo depois.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fw2wv29k7b06ysb492xqj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fw2wv29k7b06ysb492xqj.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com a anotação @Retry, caso ocorra alguma exceção, a aplicação tentará executar o mesmo código várias vezes (até um limite estabelecido). Caso não consiga executar, daí então é que ela vai realmente estourar a exceção. O código com a retentativa fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
  &lt;span class="nd"&gt;@Retry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;tentativaComException&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;contador&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tentativa número: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" às "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O nosso código ainda retornará exceção, porém, se formos no log veremos as vezes que o sistema tentou executar o método.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tentativa número: 1 às 2021-05-18T10:24:37.996164
Tentativa número: 2 às 2021-05-18T10:24:38.000239
Tentativa número: 3 às 2021-05-18T10:24:38.101461
Tentativa número: 4 às 2021-05-18T10:24:38.292833
Tentativa número: 5 às 2021-05-18T10:24:38.338367
Tentativa número: 6 às 2021-05-18T10:24:38.338657
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notem que só por ter essa anotação, nós ganhamos o comportamento das retentativas e também temos vários tipos de controle como o tempo entre retentativas, o tempo máximo para fazer toda a operação, para quais exceções terá rentativa, etc...&lt;/p&gt;

&lt;h2&gt;
  
  
  Fallback
&lt;/h2&gt;

&lt;p&gt;O método de fallback é o método que é chamado no caso de uma exceção. Se na retentativa o sistema executava várias vezes o mesmo método, com o fallback será executado alguma outra lógica. Podemos pensar nele como uma forma mais limpa de fazer um &lt;strong&gt;try/catch&lt;/strong&gt;. O código com alterado fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nd"&gt;@Fallback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"tratamentoComFallback"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;tentativaComFallback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;tratamentoComFallback&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Hello com fallback tratado"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando o código, o retorno será:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgpd83d6rx434s92xxpgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgpd83d6rx434s92xxpgv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É importante que o método de fallback tenha a mesma assinatura do método inicial ou dará ruim. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fq3tumysnudjcgnb96zu6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fq3tumysnudjcgnb96zu6.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outra coisa bem parte legal do método de fallback é que ele trabalha muito bem com as outras anotações. Dessa forma você pode retentar fazer uma operação e, caso não consiga ou demore muito tempo, o método de fallback é executado. Fica topzeira.&lt;/p&gt;

&lt;p&gt;Por fim, existe um ponto de enorme atenção a todos. Os métodos com essas anotações não serão processados se o escopo do método for privado. Então muita atenção nesse ponto.&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações finais
&lt;/h1&gt;

&lt;p&gt;Fiquei bem feliz em conseguir voltar a escrever sobre Quarkus, principalmente por falar sobre essa extensão que tem sido uma mão na roda nas últimas semanas. Num post futuro, quero falar sobre &lt;a href="https://www.treinaweb.com.br/blog/o-que-e-circuit-breaker/" rel="noopener noreferrer"&gt;&lt;em&gt;circuit breaker&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Espero que cada vez mais as pessoas possam usar e se apaixonar por essa tecnologia incrível.&lt;br&gt;
Ah, e o código de hoje pode ser encontrado no &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/fault-tolerance" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>quarkus</category>
      <category>java</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Configurando tratamento de erros no kafka com Quarkus</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Fri, 05 Mar 2021 00:13:48 +0000</pubDate>
      <link>https://dev.to/lucasscharf/configurando-tratamento-de-erros-no-kafka-com-quarkus-308d</link>
      <guid>https://dev.to/lucasscharf/configurando-tratamento-de-erros-no-kafka-com-quarkus-308d</guid>
      <description>&lt;p&gt;Java é lindo. Quarkus é lindo. [Franz] Kafka é lindo. Porém, nem tudo são flores no desenvolvimento. Acidentes acontecem e é importante conseguirmos nos preparar para eles. Hoje, nós vamos ver sobre os diferentes tipos de tratamento de exceção durante o consumo de uma mensagem Kafka pelo Quarkus. &lt;/p&gt;

&lt;p&gt;Já vou assumir que você sabe o que é o Kafka, já manja um pouco de Quarkus e tem tudo configurado. Caso não seja o seu caso, tenho um &lt;a href="https://dev.to/lucasscharf/como-usar-kafka-num-projeto-quarkus-5d9c"&gt;artigo infinitop&lt;/a&gt; para ajudar.&lt;/p&gt;

&lt;p&gt;O Quarkus possui 3 formas diferentes para tratar uma exceção quando no método com a anotação &lt;strong&gt;@Incoming&lt;/strong&gt;: Parar de consumir mensagens, ignorar e DLQ (&lt;em&gt;dead-letter queue&lt;/em&gt;). &lt;/p&gt;

&lt;h1&gt;
  
  
  Parar de consumir mensagens
&lt;/h1&gt;

&lt;p&gt;Esse é o tratamento padrão. O serviço continuará funcionando normalmente. Porém, as mensagens não serão mais consumidas até que alguém intervenha na mensagem, resolva o que precisar ser resolvido e então reinicie o serviço.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkjlo7mrgnpu0uuss9v85.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkjlo7mrgnpu0uuss9v85.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caso nada tenha sido configurado, será utilizado essa opção.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ignorar
&lt;/h1&gt;

&lt;p&gt;Nesse modo, caso ocorra alguma exceção, o Quarkus diz pro Kafka que conseguiu consumir corretamente a mensagem e finge que o erro nunca existiu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Flage0tb3u5fgb969ffh8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Flage0tb3u5fgb969ffh8.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para configurar é muito simples. Basta adicionar o seguinte trecho no application.properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;mp.messaging.incoming.&amp;lt;nome&lt;/span&gt; &lt;span class="err"&gt;do&lt;/span&gt; &lt;span class="err"&gt;canal&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.failure-strategy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Dead-letter queue
&lt;/h1&gt;

&lt;p&gt;Nesse modo, quando ocorre uma exceção, o Quarkus ainda irá informar ao Kafka que a mensagem foi consumida, porém, irá enviar a mensagem para uma fila especial onde essas mensagens poderão ser consumidas num momento oportuno.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F4naf86ijgndhjsdj9xos.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F4naf86ijgndhjsdj9xos.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa é a configuração que tem mais opções, mas é bem simples de entender:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;mp.messaging.incoming.&amp;lt;nome&lt;/span&gt; &lt;span class="err"&gt;do&lt;/span&gt; &lt;span class="err"&gt;canal&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.failure-strategy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dead-letter-queue&lt;/span&gt;
&lt;span class="err"&gt;mp.messaging.incoming.&amp;lt;nome&lt;/span&gt; &lt;span class="err"&gt;do&lt;/span&gt; &lt;span class="err"&gt;canal&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.dead-letter-queue.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;nome do tópico de DLQ&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;mp.messaging.incoming.&amp;lt;nome&lt;/span&gt; &lt;span class="err"&gt;do&lt;/span&gt; &lt;span class="err"&gt;canal&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.dead-letter-queue.key.serializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;caminho para o serializador da chave&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;mp.messaging.incoming.&amp;lt;nome&lt;/span&gt; &lt;span class="err"&gt;do&lt;/span&gt; &lt;span class="err"&gt;canal&amp;gt;&lt;/span&gt;&lt;span class="py"&gt;.dead-letter-queue.value.serializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;caminho para o serializador do valor da mensagem&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por padrão, o nome do tópico será o "dead-letter-topic-" + nome do canal. Além disso, o Quarkus tentará supor o caminho para o serializador. É possível seguir o palpite dele, ou configurar manualmente. &lt;strong&gt;O destino está nas suas mãos.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uma outra observação importante é que, se o tópico de DLQ não existe, então o Quarkus irá criar um novo tópico com as configurações padrões do Kafka (o que pode não ser a melhor abordagem possível).&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações finais
&lt;/h1&gt;

&lt;p&gt;Esse é um assunto bem interessante e que eu queria ter colocado lá no &lt;a href="https://dev.to/lucasscharf/como-usar-kafka-num-projeto-quarkus-5d9c"&gt;outro post&lt;/a&gt;. Porém, achei que ficaria muita coisa. &lt;/p&gt;

&lt;p&gt;Foi estranho fazer um post sem código, mas espero que tenham gostado!&lt;/p&gt;

</description>
      <category>java</category>
      <category>braziliandevs</category>
      <category>quarkus</category>
      <category>kafka</category>
    </item>
    <item>
      <title>Quarkus e TestContainers o Pikachu dos ambientes de testes</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Mon, 08 Feb 2021 15:15:13 +0000</pubDate>
      <link>https://dev.to/lucasscharf/quarkus-e-testcontainers-o-pikachu-dos-ambientes-de-testes-omb</link>
      <guid>https://dev.to/lucasscharf/quarkus-e-testcontainers-o-pikachu-dos-ambientes-de-testes-omb</guid>
      <description>&lt;p&gt;Me considero uma pessoa que pensa no bem comum e em ajudar o próximo. Por exemplo, caso eu encontrasse um gênio que me desse direito a um único desejo, eu escolheria que os pokémons existissem no mundo real. Porém, se ele me desse direito a um segundo desejo, eu escolheria que todos os desenvolvedores soubessem usar os &lt;a href="https://www.testcontainers.org/" rel="noopener noreferrer"&gt;test containers&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é?
&lt;/h1&gt;

&lt;p&gt;O Testcontainers é uma biblioteca Java que permite subir instâncias docker durantes o ciclo de testes. Com essas instâncias, é possível ter acesso ao banco de dados, sistema de mensageria, cache, etc... &lt;/p&gt;

&lt;p&gt;Mas é importante ter atenção pra algo muito importante:&lt;br&gt;
&lt;strong&gt;É NECESSÁRIO TER O DOCKER INSTALADO NA MÁQUINA QUE FOR RODAR OS TESTES.&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  O que faremos?
&lt;/h1&gt;

&lt;p&gt;O teste de hoje será um pouco mais elaborado. Vamos usar o que nós já aprendemos sobre &lt;a href="https://dev.to/lucasscharf/trabalhando-com-jpa-quarkus-panache-e-bolo-de-chocolate-36k7"&gt;banco de dados&lt;/a&gt; e &lt;a href="https://dev.to/lucasscharf/como-usar-kafka-num-projeto-quarkus-5d9c"&gt;mensageria&lt;/a&gt;. Vamos criar uma classe que cria um Pokémon e armazena ele no c̶i̶n̶t̶o̶ ̶d̶e̶ ̶p̶o̶k̶e̶b̶ó̶l̶a̶s̶ banco de dados. &lt;br&gt;
Após isso, será disparado um evento ao kafka onde um treinador rival irá batalhar e nós recuperaremos o nosso pokémon para a batalha.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcrqs3wr9flns1x92i971.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcrqs3wr9flns1x92i971.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Hora da ação
&lt;/h1&gt;

&lt;p&gt;Primeiramente vamos configurar nosso ambiente com as dependências necessárias. Por isso, é necessário adicionar a seguinte configuração no nosso pom.xml. Essas extensões configuram o conector de mensagens Kafka, a comunicação com banco de dados (via Panache) e o Test Containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&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.quarkus&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;quarkus-smallrye-reactive-messaging-kafka&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.quarkus&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;quarkus-jdbc-postgresql&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.quarkus&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;quarkus-hibernate-orm-panache&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;org.testcontainers&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;testcontainers&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.15.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&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;org.testcontainers&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;kafka&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.15.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&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;p&gt;Segundamente, vamos criar nossa classe de Pokémon. Ela é bem simples, tem o nome e o número dele. Isso é feito através da classe abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.acme&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.persistence.Entity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.quarkus.hibernate.orm.panache.PanacheEntity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Entity&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;Pokemon&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PanacheEntity&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;codigo&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;nome&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;codigo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getCodigo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getNome&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos fazer nosso gerador de batalhas. Ao receber uma mensagem de que um treinador rival quer entrar em batalha (recebendo o nome do treinador), ele gravará no log o nome do treinador, pegará o primeiro pokémon disponível no banco de dados e gravará no log o nome desse pokémon. O código da batalha está baixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.acme&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.transaction.Transactional&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.microprofile.reactive.messaging.Incoming&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.Logger&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.smallrye.reactive.messaging.annotations.Blocking&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&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;GeradorDeBatalha&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;PRIMEIRO_ELEMENTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

  &lt;span class="nd"&gt;@Incoming&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"novo-combate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@Blocking&lt;/span&gt;
  &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;iniciarCombate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nomeDoTreinador&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"O treinador [{}] quer iniciar um combate"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nomeDoTreinador&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Pokemon&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listAll&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PRIMEIRO_ELEMENTO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[{}], eu escolho você!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getNome&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos fazer o nosso teste. Por fins didáticos, não fazemos nenhum tipo de asserção sobre ele, apenas olhando &lt;br&gt;
o logo impresso. Como são threads diferentes que irão fazer o processamento (uma thread vai emitir a mensagem de batalha e a outra vai consumir), nós precisamos dar um tempo na nossa thread de teste para que a outra faça o seu trabalho.&lt;/p&gt;

&lt;p&gt;O código para testes é esse aqui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.acme&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.inject.Inject&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.transaction.Transactional&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.microprofile.reactive.messaging.Channel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.microprofile.reactive.messaging.Emitter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.BeforeEach&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.quarkus.test.common.QuarkusTestResource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.quarkus.test.junit.QuarkusTest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@QuarkusTest&lt;/span&gt;
&lt;span class="nd"&gt;@QuarkusTestResource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Dependencias&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&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;BatalhaTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@Channel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"iniciar-combate"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@Inject&lt;/span&gt;
  &lt;span class="nc"&gt;Emitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;emissor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@BeforeEach&lt;/span&gt;
  &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;cadastrarPokemon&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Pokemon&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pokemon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Pikachu"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Test&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;combateSimples&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;emissor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gary Carvalho"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1_000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feito isso, vamos configurar o &lt;strong&gt;application.properties&lt;/strong&gt; com o banco de dados, um consumidor e um emissor de mensagens de combate (esse emissor será usado só para os testes).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;quarkus.datasource.db-kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ash&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;pallet&lt;/span&gt;
&lt;span class="py"&gt;quarkus.datasource.jdbc.url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;jdbc:postgresql://localhost:5432/pokemon&lt;/span&gt;

&lt;span class="py"&gt;quarkus.hibernate-orm.database.generation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;update&lt;/span&gt;


&lt;span class="py"&gt;mp.messaging.incoming.novo-combate.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.novo-combate.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;novo-combate&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.novo-combate.value.deserializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;

&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;test.mp.messaging.outgoing.iniciar-combate.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;test.mp.messaging.outgoing.iniciar-combate.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;novo-combate&lt;/span&gt;
&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;test.mp.messaging.outgoing.iniciar-combate.value.serializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.apache.kafka.common.serialization.StringSerializer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso tenha ficado alguma dúvida sobre o funcionamento da parte de configuração, tem dois posts topzeiras &lt;a href="https://dev.to/lucasscharf/configurando-sua-aplicacao-java-com-quarkus-configproperty-2h2c"&gt;aqui&lt;/a&gt; e &lt;a href="https://dev.to/lucasscharf/alterando-o-perfil-de-configuracao-do-quarkus-cn8"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tudo certo né? Agora é só mandar o maven testar e podemos ser felizes. Certo? Errado!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft81d1qm1t65inee243pw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft81d1qm1t65inee243pw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como não existe nem o banco de dados rodando e nem o kafka, a aplicação nem subirá direito. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7wkhpofbnqzcqczwrxet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7wkhpofbnqzcqczwrxet.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para que a aplicação suba corretamente, é necessário fazer as dependências rodarem e é aqui que os &lt;strong&gt;tests containers&lt;/strong&gt; entram. &lt;/p&gt;

&lt;p&gt;Nós já configuramos eles, agora basta criarmos os containers para testes. Isso pode ser feito através da classe abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;org.acme&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.HashMap&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testcontainers.containers.GenericContainer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testcontainers.containers.KafkaContainer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.testcontainers.utility.DockerImageName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.quarkus.test.common.QuarkusTestResourceLifecycleManager&lt;/span&gt;&lt;span class="o"&gt;;&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;Dependencias&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;QuarkusTestResourceLifecycleManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;KafkaContainer&lt;/span&gt; &lt;span class="n"&gt;kafka&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KafkaContainer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DockerImageName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"confluentinc/cp-kafka"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;//0&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DockerImageName&lt;/span&gt; &lt;span class="no"&gt;POSTGRES_IMAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DockerImageName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres:12-alpine"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;GenericContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;postgresContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GenericContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="no"&gt;POSTGRES_IMAGE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//2&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withEnv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POSTGRES_USER"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"usuario"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;// 3&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withEnv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POSTGRES_PASSWORD"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"senha"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withExposedPorts&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;// 4&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withEnv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POSTGRES_DB"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bancoDeDados"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 5&lt;/span&gt;
    &lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;//6&lt;/span&gt;

    &lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;//7&lt;/span&gt;

    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quarkus.datasource.username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"usuario"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//8&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quarkus.datasource.password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"senha"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quarkus.datasource.jdbc.url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="s"&gt;"jdbc:postgresql://"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHost&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;postgresContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFirstMappedPort&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/bancoDeDados"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;//9&lt;/span&gt;
    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kafka.bootstrap.servers"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBootstrapServers&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;&lt;span class="c1"&gt;//10&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa é a classe que cria os containers. Vamos entender o que ela faz?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 - Container kafka que já tem tudo pré-configurado (ter um container desses é muito útil)&lt;/li&gt;
&lt;li&gt;1 - Imagem docker para a utilização de um container genérico&lt;/li&gt;
&lt;li&gt;2 - Container genérico, onde vamos configurar os valores para fazer nossos testes&lt;/li&gt;
&lt;li&gt;3 - Configuração do usuário&lt;/li&gt;
&lt;li&gt;4 - Configuração da senha&lt;/li&gt;
&lt;li&gt;5 - Configuração do banco (notem que é uma boa prática usar valores diferentes dos que estão no &lt;strong&gt;application.properties&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;6 - Expondo a porta interna 5432 (o testContainers poderá mapear essa porta interna para alguma outra porta externa)&lt;/li&gt;
&lt;li&gt;7 - Iniciando o container postgres&lt;/li&gt;
&lt;li&gt;8 - Iniciando o container kafka&lt;/li&gt;
&lt;li&gt;9 - Atualizando as configurações que serão utilizadas durante o teste&lt;/li&gt;
&lt;li&gt;10 - Na falta de um container específico, as configurações ficam assim e isso pode gerar erros&lt;/li&gt;
&lt;li&gt;11 - Utilização de propriedade com container específico&lt;/li&gt;
&lt;li&gt;12 - Retornando as propriedades&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E nós só precisamos de mais um passo que é informar para a nossa classe de teste de que é para ele utilizar o nosso recurso de teste. Isso é feito colocando a anotação de classe&lt;br&gt;
&lt;code&gt;@QuarkusTestResource(Dependencias.class)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Agora sim é só rodar a nossa aplicação com o &lt;code&gt;mvn test&lt;/code&gt; e correr pro abraço.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2021-02-08 12:08:14,720 INFO  &lt;span class="o"&gt;[&lt;/span&gt;org.acm.GeradorDeBatalha_Subclass] &lt;span class="o"&gt;(&lt;/span&gt;vert.x-worker-thread-1&lt;span class="o"&gt;)&lt;/span&gt; O treinador &lt;span class="o"&gt;[&lt;/span&gt;Gary Carvalho] quer iniciar um combate
2021-02-08 12:08:14,811 INFO  &lt;span class="o"&gt;[&lt;/span&gt;org.acm.GeradorDeBatalha_Subclass] &lt;span class="o"&gt;(&lt;/span&gt;vert.x-worker-thread-1&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Pikachu], eu escolho você!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Fiz um resumão super resumido sobre os tests containers e Quarkus. Tem bastante coisa pra falar e espero fazer mais posts sobre isso. Outra coisa interessante é que notei que boa parte dos meus textos são sobre testes e estou feliz com isso. Um mundo com mais testes, é um mundo mais feliz.&lt;/p&gt;

&lt;p&gt;Ah, e o código de hoje pode ser encontrado no &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/test-containers" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>java</category>
      <category>quarkus</category>
      <category>quarkusio</category>
    </item>
    <item>
      <title>Alterando o perfil de configuração do Quarkus</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Wed, 03 Feb 2021 01:06:48 +0000</pubDate>
      <link>https://dev.to/lucasscharf/alterando-o-perfil-de-configuracao-do-quarkus-cn8</link>
      <guid>https://dev.to/lucasscharf/alterando-o-perfil-de-configuracao-do-quarkus-cn8</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/lucasscharf/configurando-sua-aplicacao-java-com-quarkus-configproperty-2h2c"&gt;Num post passado&lt;/a&gt;, nós já vimos bastante sobre como injetar configurações no Quarkus. Mas a parte de configuração do Quarkus é tão linda que deveria ser exposto num museu como o Louvre e dá vontade de falar bastante sobre ela. No post de hoje, nós vamos ver como alterar o Perfil de configuração.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é esse tal de perfil de configuração?
&lt;/h1&gt;

&lt;p&gt;Se você já leu o &lt;a href="https://dev.to/lucasscharf/configurando-sua-aplicacao-java-com-quarkus-configproperty-2h2c"&gt;outro post&lt;/a&gt; e entendeu o que são os perfis de configuração, pode passar pro próximo tópico. Se você não leu e não vai ler, não se preocupe vou explicar de novo porque o̶ ̶e̶d̶i̶t̶o̶r̶ ̶m̶e̶ ̶o̶b̶r̶i̶g̶o̶u̶ ̶a̶ ̶t̶e̶r̶ ̶u̶m̶ ̶n̶ú̶m̶e̶r̶o̶ ̶m̶í̶n̶i̶m̶o̶ ̶d̶e̶ ̶p̶a̶l̶a̶v̶r̶a̶s̶ ̶n̶o̶ ̶p̶o̶s̶t̶ eu gosto muito de você &amp;lt;3&lt;/p&gt;

&lt;h1&gt;
  
  
  O que faremos
&lt;/h1&gt;

&lt;p&gt;Vamos reutilizar a classe ConfigResource do &lt;a href="https://dev.to/lucasscharf/configurando-sua-aplicacao-java-com-quarkus-configproperty-2h2c"&gt;post sobre @ConfigProperty&lt;/a&gt; (é sério, vai lá, é um post bem legal), mas vamos adicionar configurações para serem utilizadas no ambiente de QA (que é um perfil diferente de test, prod ou dev). Depois disso, vamos chamar a nossa aplicação com o perfil de QA e vamos ver a magia acontecer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipaqwfug1bptrcj4zgsw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipaqwfug1bptrcj4zgsw.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Hora da ação
&lt;/h1&gt;

&lt;p&gt;Após pegar o de exemplo de configuração lá no github, nós vamos rodá-lo através do comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn quarkus:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e acessar a página de configuração &lt;code&gt;/config&lt;/code&gt; para ver as configurações salvas.&lt;/p&gt;

&lt;p&gt;Nisso, vamos ter o seguinte resultado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu1dxxxvxadwhbwypiy3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu1dxxxvxadwhbwypiy3f.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, vamos alterar o arquivo application.properties e adicionar o seguinte trecho:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;test.config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Configuração simples de teste&lt;/span&gt;
&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;qa.config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Configuração simples de QA&lt;/span&gt;
&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="py"&gt;dev.config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Configuração simples em dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, nós mudamos o valor da configuração para diferentes perfis. Quando estamos usando o &lt;code&gt;quarkus:dev&lt;/code&gt;, nós estamos com o perfil de dev. Se nós atualizarmos a nossa página, nós já vamos ver uma mensagem diferente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjbz6e01bi0gzb327twj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjbz6e01bi0gzb327twj8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se fosse em produção (ou em teste, o resultado seria diferente). Aproveite para testar e ver a magia acontecer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usando um perfil não padrão
&lt;/h2&gt;

&lt;p&gt;Além de termos adicionado opções para perfis de teste e de desenvolvimento, nós também adicionamos um perfil de QA. Mas fica a dúvida, como fazer para ativar esse perfil?&lt;/p&gt;

&lt;p&gt;Para fazer isso, basta passar a configuração -Dquarkus.profile.&lt;/p&gt;

&lt;p&gt;Para rodar com o perfil de QA, basta usar o seguinte código&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn quarkus:dev &lt;span class="nt"&gt;-Dprofile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;QA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, o restultado final será:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg2ul6np5lklb0l9hcd2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg2ul6np5lklb0l9hcd2d.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Cada vez mais, gosto desse processo de compartilhar conhecimento e esse foi o meu primeiro post para adicionar algo que eu já falei num post passado. Estou todo bobo :3&lt;/p&gt;

&lt;p&gt;Também aproveitei pra fazer algo mais simples e direto. Espero que tenham gostado.&lt;/p&gt;

&lt;p&gt;Ah, e o código de hoje pode ser encontrado no &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/config-with-profile" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>ptbr</category>
      <category>quarkus</category>
      <category>java</category>
    </item>
    <item>
      <title>Boas práticas para usar o git</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Tue, 05 Jan 2021 13:44:10 +0000</pubDate>
      <link>https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e</link>
      <guid>https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e</guid>
      <description>&lt;p&gt;Seja bem vindo a mais uma ~gentil~ introdução ao git. Chegamos ao nosso último post e vamos ver sobre algumas boas práticas para utilizar o git. &lt;br&gt;
Caso você queira saber sobre tudo o que nós falamos até agora, basta olhar esse mapa maroto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;O que é o GIT e como usar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;Principais comandos do git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;Como fazer um rebase de presença&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj"&gt;Como escrever um README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Boas práticas para utilizar o git ⟵ você está aqui&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Dicas Gerais
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Conhecer bem o git
&lt;/h2&gt;

&lt;p&gt;O git é uma ferramenta ótima. Porém, &lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;como já vimos&lt;/a&gt;, ele tem comando pra caramba. Não tô dizendo para vocês virarem especialistas no git, mas é importante conhecer bem os comandos, entender como funciona a árvore de commits, &lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;saber fazer bem um rebase&lt;/a&gt;, saber ler um reflog, entender os diferentes tipos de merge, etc...&lt;/p&gt;
&lt;h2&gt;
  
  
  Saber usar a linha de comando
&lt;/h2&gt;

&lt;p&gt;As ferramentas gráficas para git são bem interessantes e ajudam bastante. Mas tem muitas coisas que só dá para fazer corretamente pela linha de comando. O quanto antes aprender a mexer no git pela linha de comando, melhor.&lt;/p&gt;
&lt;h2&gt;
  
  
  Siga padrões
&lt;/h2&gt;

&lt;p&gt;É extremanete importante que todos os colaboradores falem a mesma língua, escrevam commits da mesma forma e sigam o mesmo fluxo de trabalho. Se não, fica praticamente impossível restrear qualquer coisa no git.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usar sempre o mesmo idioma
&lt;/h2&gt;

&lt;p&gt;Ainda na linha de padrões, é &lt;strong&gt;necessário usar o mesmo idioma&lt;/strong&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  Configurar corretamente a autoria
&lt;/h2&gt;

&lt;p&gt;A autoria permite saber quem exatamente fez cada commit (o famoso git blame). É bem simples, basta usar os seguintes comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Seu nome"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email seu_email@exemplo.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usar um repositório por projeto
&lt;/h2&gt;

&lt;p&gt;A menos que tenham pessoas que sabem o que estão fazendo para trabalhar como um projeto mono repo, utilize um repositório por projeto. Várias aplicações por projeto é a receita para o caos e confusão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ter um workflow (e fazer as pessoas seguirem)
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Adicionar um pipeline de CD
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Use boas ferramentas
&lt;/h2&gt;

&lt;p&gt;O git sozinho já é ótimo e existem algumas ferramentas que podem ajudar bastante em atividades específicas (visualizar a árvore de commits, fazer o blame automático enquanto você escreve o código, ajudar a ver os conflito, etc...).&lt;/p&gt;

&lt;p&gt;Particularmente, eu uso o VSCode para resolver conflitos (com o plugin do gitlens) e o tig para ver a árvore. Vejo muita gente usando o git kraken, mas nunca usei.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usar repositórios de template
&lt;/h2&gt;

&lt;p&gt;O Github tem uma ferramenta ótima q̶u̶e̶ ̶d̶e̶v̶e̶r̶i̶a̶ ̶s̶e̶r̶ ̶c̶o̶p̶i̶a̶d̶a̶ ̶p̶e̶l̶o̶ ̶b̶i̶t̶b̶u̶c̶k̶e̶t̶ para quem trabalha com vários projetos que é criar um template de repositório com todas as coisas corretamente configuradas. Isso acelera muito o processo de desenvolvimento&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft3zwaopl8esqams42upa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft3zwaopl8esqams42upa.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dicas para bons &lt;em&gt;commits&lt;/em&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Anotar a issue
&lt;/h2&gt;

&lt;p&gt;Via de regra, você trabalhará com algum sistema de gestão de atividades/issues/tickets integrado com o seu git. No footer de cada commit, basta indicar a commit issue o commit se refere. Isso adiciona mais rastreabilidade no que foi feito e permite indica o caminho de documentações que não cabem dentro de uma mensagem de commit &lt;/p&gt;

&lt;h2&gt;
  
  
  Considerar os commits como documentação
&lt;/h2&gt;

&lt;p&gt;Para muitas empresas, os commits não representam nada em relação ao código. Porém, ele é uma boa fonte de documentação histórica do código. &lt;/p&gt;

&lt;h2&gt;
  
  
  Escrever o que foi feito, o que não foi feito e porque
&lt;/h2&gt;

&lt;p&gt;No uma boa mensagem de commit tem o que foi feito, o porque foi feito e o que tentou fazer mas não deu certo (claro que dentro do bom senso, afinal, nem todos os commits carregam esse peso). &lt;/p&gt;

&lt;h2&gt;
  
  
  Usar título
&lt;/h2&gt;

&lt;p&gt;A primeira linha de um commit serve como título. É ela quem aparecerá dentro das ferramentas e na hora de ler o log. Por isso é importante uma descrição simples do que aquele commit representa (de preferência com menos de 80 caracteres)&lt;/p&gt;

&lt;h1&gt;
  
  
  Dicas para bons Pull Requests
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Fazer vários commits, porém fazer o rebase
&lt;/h2&gt;

&lt;p&gt;Uma das funções do git é servir de backup remoto. Você pode fazer commits diretos com as tentativas de arrumar um problema, ou mesmo fazer commits todos os dias. Na hora do PR, é só juntar as alterações feitas, descartar o lixo e fazer um ou mais commits relevantes. &lt;br&gt;
O mesmo serve para a revisão de código de um PR. Basta ir fazendo as alterações necessárias e depois fazer um rebase para unir tudo com o commit principal. Isso gera uma árvore limpa e fácil de navegar. &lt;/p&gt;

&lt;h2&gt;
  
  
  Quando fazer o PR, já adicionar os testes
&lt;/h2&gt;

&lt;p&gt;Sempre que possível, já adicione os testes dentro do PR. Além de ajudar a entender melhor o que foi feito, garante que a cobertura de testes do sistema permanecerá alta. &lt;/p&gt;

&lt;h2&gt;
  
  
  Fazer PR apenas de coisas relacionadas
&lt;/h2&gt;

&lt;p&gt;Se você adicionou uma funcionalidade, abre um PR para isso e só isso. Não é para colocar formatação de arquivo ou outras coisas nesse PR. &lt;/p&gt;

&lt;h2&gt;
  
  
  Não integrar código comentado
&lt;/h2&gt;

&lt;p&gt;O git já consegue manter o histórico de tudo o que foi feito. Se você seguir boas práticas, não há necessidade para fazer PR com código comentado&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2rrs290hccdtdio4v4xz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2rrs290hccdtdio4v4xz.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dicas para ter uma boa árvore
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Evitar de reescrever a história da Master
&lt;/h2&gt;

&lt;p&gt;Aqui estou falando de qualquer branch que mais de uma pessoa utiliza. Quando rola rebases, é possível que o trabalho de um acabe prejudicando o de outro. &lt;/p&gt;

&lt;h2&gt;
  
  
  Manter o repositório local atualizado (de preferência com rebase)
&lt;/h2&gt;

&lt;p&gt;É só ficar fazendo &lt;code&gt;git fetch --all&lt;/code&gt; e &lt;code&gt;git rebase origin/&amp;lt;nome da branch principal&amp;gt;&lt;/code&gt; que você vai manter a sua árvore sempre atualizada e isso evita maiores dores de cabeça na hora de criar o PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abrir branchs
&lt;/h2&gt;

&lt;p&gt;Se você trabalha com outras pessoas, não é bom trabalhar diretamente na branch principal. É p̶r̶o̶v̶á̶v̶e̶l̶ possível que alguém acabe fazendo um rebase que não deve ou algo assim. Por isso é bom sempre abrir uma branch, fazer suas alterações e então mergear via pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proteger a master
&lt;/h2&gt;

&lt;p&gt;Acidentes acontecem, por isso é importante impedir as pessoas de fazerem &lt;em&gt;pushs&lt;/em&gt; direto na master ou develop. Isso é feito através da configuração do repositório. &lt;/p&gt;

&lt;h2&gt;
  
  
  Não comitar grandes arquivos binários
&lt;/h2&gt;

&lt;p&gt;O git funciona muito bem para arquivos de textos e pequenos binários (coisa de alguns KB). No momento que você começa a colocar arquivos maiores, começa o diretório .git começa a dar ruim (principalmente se você mexer muito nesse arquivo)&lt;/p&gt;

&lt;h2&gt;
  
  
  Usar um bom .gitignore
&lt;/h2&gt;

&lt;p&gt;Um bom .gitiginore ajuda a evitar o envio de arquivos binários. Eu Eu gosto bastante o do &lt;a href="https://www.toptal.com/developers/gitignore" rel="noopener noreferrer"&gt;gitiginore.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>braziliandevs</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Como escrever um bom README.md</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Mon, 28 Dec 2020 00:50:46 +0000</pubDate>
      <link>https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj</link>
      <guid>https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj</guid>
      <description>&lt;p&gt;Fala galerinha do barulho, prontos para se meterem em um monte de confusão enquanto seguimos desbravando como funciona o git?&lt;/p&gt;

&lt;p&gt;Pra você não se perder, segue o nossa mapa maroto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;O que é o GIT e como usar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;Principais comandos do git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;Como fazer um rebase de presença&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Como escrever um README.md ⟵ você está aqui&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e"&gt;Boas práticas para utilizar o git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Já aprendemos &lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;o que é o git&lt;/a&gt;, já aprendemos quais são os &lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;principais comandos&lt;/a&gt; e até aprendemos &lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;conquistar pessoas nas baladas da vida&lt;/a&gt; usando o rebase. &lt;br&gt;
No episódio de hoje, nós vamos dar um passo além na nossa jornada e aprender a fazer um documento README topzeira.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é o README?
&lt;/h1&gt;

&lt;p&gt;É um documento do tipo &lt;em&gt;markdown&lt;/em&gt; (que é tipo um html simplificado) que descreve informações importantes sobre o seu projeto. &lt;a href="https://medium.com/@raullesteves/github-como-fazer-um-readme-md-bonit%C3%A3o-c85c8f154f8" rel="noopener noreferrer"&gt;Esse artigo&lt;/a&gt; explica bem como faz para escrever um &lt;em&gt;markdown&lt;/em&gt;. Nós vamos nos focar mais no conteúdo e menos nesses detalhes de tags. &lt;/p&gt;

&lt;p&gt;Logo abaixo, nós teremos quais sessões devem ter nesse  documento de descrição (incluindo quais sessões são opcionais) para você colocar no seu projeto do git. &lt;/p&gt;

&lt;h2&gt;
  
  
  Nome do projeto
&lt;/h2&gt;

&lt;p&gt;A primeira parte do projeto é para ser o nome do projeto. Com uma tag de título (#). Eu sei que quem for ler consegue ler o nome na URL, mas a ideia é simplificar a vida de quem está lendo tudo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opcional: Logo, &lt;em&gt;Badges&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Sem tags de título, aqui nós colocamos qualquer &lt;em&gt;badge&lt;/em&gt; que possa ser interessante para o projeto (status do jenkins, número de vezes que o projeto foi clonado, estrelas no github, etc...). Também vamos colocar logo e as coisas que identifiquem graficamente o projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opcional: Status do projeto caso ele já esteja morto
&lt;/h2&gt;

&lt;p&gt;Ninguém é obrigado a dar manuntenção num projeto para sempre. Caso você tenha decidido deixar o projeto de lado ou não consiga mais contribuir mais com ele é importante deixar claro aos demais que não haverá mais atualizações. &lt;br&gt;
Isso evita bastante frustração para as partes envolvidas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Descrição do projeto (em um parágrafo)
&lt;/h2&gt;

&lt;p&gt;Também sem tag, aqui é o momento de explicar sucintamente o que o projeto faz. O ideal é que não passe de um parágrafo. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5tzxtjjt56gt123ngb8k.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5tzxtjjt56gt123ngb8k.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como rodar
&lt;/h2&gt;

&lt;p&gt;Todo o sistema tem pré requisitos para rodar (o menor deles é você ter um computador). Essa sessão serve para explicar o que o usuário precisa para baixar/instalar/rodar o  sistema. &lt;br&gt;
Caso o sistema tenha as dependências em docker, é importante colocar o docker-compose.yml e linká-lo aqui.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como testar
&lt;/h2&gt;

&lt;p&gt;Tão importante quanto rodar a aplicação é fazer a rotina de testes. Aqui é explicado como a aplicação é testada, se é necessário levantar alguma dependência para os testes ou mesmo se existe a̶l̶g̶u̶m̶a̶ ̶m̶a̶g̶i̶a̶ algum comando especial para executar os testes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Propriedades/variáveis de ambiente
&lt;/h2&gt;

&lt;p&gt;Como falei lá no &lt;a href="https://dev.to/lucasscharf/configurando-sua-aplicacao-java-com-quarkus-configproperty-2h2c"&gt;post sobre configuração&lt;/a&gt;. "Não tem jeito. Inevitavelmente um software precisa de algum tipo de configuração. Seja as credenciais de acesso ao banco de dados, o endereço de algum serviço externo, regras de log, etc..."&lt;br&gt;
Essa sessão, serve para explicar quais são as principais propriedades do sistema, para o que elas servem e como/onde alterar. &lt;/p&gt;

&lt;h2&gt;
  
  
  Opcional: como contribuir/como ajudar
&lt;/h2&gt;

&lt;p&gt;Se o projeto é um software livre, então é muito importante explicar para as pessoas como elas podem ajudar. &lt;br&gt;
Esse espaço também serve para você deixar links de doação. &lt;/p&gt;

&lt;h2&gt;
  
  
  Opcional: &lt;em&gt;Acknowledgements&lt;/em&gt; ou Agradecimentos
&lt;/h2&gt;

&lt;p&gt;Esse espaço serve exclusivamente para os desenvolvedores se promoverem. Caso alguém esteja realmente interessado em saber quem trabalhou no projeto, a pessoa consegue ir no histórico de &lt;em&gt;commits&lt;/em&gt;. &lt;br&gt;
Particularmente, considero um desperdício de espaço. &lt;/p&gt;

&lt;h1&gt;
  
  
  Dicas gerais
&lt;/h1&gt;

&lt;p&gt;Essas dicas foram testadas no github, mas os demais serviços devem ter soluções parecidas. &lt;/p&gt;

&lt;h2&gt;
  
  
  Não usar &lt;em&gt;changelog&lt;/em&gt;/&lt;em&gt;releases&lt;/em&gt; no README.md
&lt;/h2&gt;

&lt;p&gt;É possível usar a aba &lt;em&gt;releases&lt;/em&gt; do github para colocar o histórico de alterações. Fica mais limpo. &lt;br&gt;
Também é possível criar um arquivo chamado CHANGELOG.md para as alterações sem a necessidade de ficar poluindo o README.md.&lt;/p&gt;

&lt;h2&gt;
  
  
  Não usar link para licença
&lt;/h2&gt;

&lt;p&gt;Você pode colocar o conteúdo da licença num arquivo LICENSE.txt que o github vai entender qual licença é.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usar &lt;em&gt;template&lt;/em&gt; de repositório
&lt;/h2&gt;

&lt;p&gt;Caso você precise fazer vários projetos. Você pode criar um &lt;em&gt;template&lt;/em&gt; para servir de modelo e ir seguindo ele.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>ptbr</category>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>Como fazer um rebase de presença</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Sun, 20 Dec 2020 15:59:17 +0000</pubDate>
      <link>https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7</link>
      <guid>https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7</guid>
      <description>&lt;p&gt;Seja bem vindo a mais uma ~gentil~ introdução ao git. Hoje, nós vamos aprender a como fazer um rebase de presença e deixar a nossa árvora de commits um pitelzinho.&lt;/p&gt;

&lt;p&gt;Antes de começar, vamos lembrar do nosso planejamento de posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;O que é o GIT e como usar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;Principais comandos do git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Como fazer um rebase de presença ⟵ você está aqui&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj"&gt;Como escrever um README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e"&gt;Boas práticas para utilizar o git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Porque essa é uma introdução bem gentil, vamos dividir o conteúdo sobre nosso &lt;em&gt;rebase&lt;/em&gt; em algumas partes. O que é uma &lt;em&gt;branch&lt;/em&gt;? O que é um &lt;em&gt;rebase&lt;/em&gt; e como ele funciona? Quais são as opções de um &lt;em&gt;rebase&lt;/em&gt; interativo? Um pequeno exemplo de como fazer um rebase para conquistar o coração daquele pichadão/tchutchuca que tá te filmando e quer ser seu namorado.&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é uma branch?
&lt;/h1&gt;

&lt;p&gt;Quando nós fazemos um &lt;em&gt;commit&lt;/em&gt;, git cria um objeto que indica quais mudanças foram feitas. Esse objeto tem um monte de informação interessante como autor, horário, &lt;em&gt;hash&lt;/em&gt; e os pais do commit. &lt;/p&gt;

&lt;p&gt;Uma branch é, apenas, um ponteiro para algum desses &lt;em&gt;commits&lt;/em&gt;. Ao fazer um &lt;em&gt;commit&lt;/em&gt;, é adicionado um novo nó nessa árvore e o ponteiro é deslocado para esse novo nó. E quandos nós criamos uma nova &lt;em&gt;branch&lt;/em&gt;, nós estamos apenas criando um novo ponteiro apontando para aquele &lt;em&gt;commit&lt;/em&gt;. A imagem abaixo mostra isso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fotu3ozthmb6a1vpwo35a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fotu3ozthmb6a1vpwo35a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Temos três &lt;em&gt;commits&lt;/em&gt;, 98ca9, 34ac2 e f30ab. Inicialmente, tínhamos uma única branch (master) apontando para o commit f360ab. Após o comando &lt;code&gt;git checkout -b testing&lt;/code&gt; criamos a &lt;em&gt;branch&lt;/em&gt; testing que também aponta para o mesmo local. &lt;/p&gt;

&lt;p&gt;Se nós estivermos na branch testing e fizemos um commit (vamos chamar de 87ab2), a testing irá apontar para esse novo commit, enquanto a branch master continuará apontando para o f30ab.&lt;/p&gt;

&lt;p&gt;Além disso, existe ponteiro especial chamado &lt;strong&gt;HEAD&lt;/strong&gt; que aponta para a &lt;em&gt;branch&lt;/em&gt; que nós estamos trabalhando. O movimento desse ponteiro poderá alterar os arquivos nós estamos vendo no nosso diretório de trabalho. E nós movimentamos o HEAD através do comando &lt;code&gt;git checkout &amp;lt;hash do commit ou nome da branch&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Na imagem abaixo, reunimos tudo o que vimos até agora. As branchs &lt;strong&gt;master&lt;/strong&gt; e &lt;strong&gt;testing&lt;/strong&gt; (com seus &lt;em&gt;commits&lt;/em&gt;) e o ponteiro HEAD.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fai8qvzhy3d04rbz2mfxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fai8qvzhy3d04rbz2mfxm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Num outro &lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;post&lt;/a&gt; nós vimos o funcionamento do checkout. Agora nós conseguimos entender melhor o que ele faz. Ao usar o checkout, nós estamos movimentando a HEAD. É possível movimentar tanto entre &lt;strong&gt;branchs&lt;/strong&gt; quanto entre &lt;strong&gt;commits&lt;/strong&gt;. Quando fazemos essa movimentação, o git pode alterar, adicionar ou remover arquivos. E o git sabe sempre como se achar porque dentro do objeto dos commits tem todas as informações importantes para ele trabalhar fazer o que precisa ser feito. &lt;/p&gt;

&lt;p&gt;Na imagem abaixo, nós fizemos um &lt;code&gt;git checkout master&lt;/code&gt; e fomos para a &lt;em&gt;branch&lt;/em&gt; master. Depois disso, criamos um novo commit (c2b9e). Desse ponto em diante, as duas &lt;em&gt;branchs&lt;/em&gt; começam a divergir e terão um ancestral comum (f30ab).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4j0ytxnh4pfndmi1e1ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4j0ytxnh4pfndmi1e1ys.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora vem a parte mágica.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F92aqzw4nbjnrkgw0qspb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F92aqzw4nbjnrkgw0qspb.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  O que é um &lt;em&gt;rebase&lt;/em&gt; e como ele funciona?
&lt;/h1&gt;

&lt;p&gt;A operação de &lt;em&gt;rebase&lt;/em&gt; reaplica os &lt;em&gt;commits&lt;/em&gt; já feitos em um árvore à partir de um determinado &lt;em&gt;commit&lt;/em&gt; ou de uma determinada &lt;em&gt;branch&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Na sua versão mais básica um rebase pode ser utilizado para sincronizar duas branchs (como o &lt;code&gt;git merge&lt;/code&gt;) com a diferença que, enquanto o git merge gera um novo commit unindo as duas branchs. O rebase aplica todos os commits novos em cima dos commits já existentes de uma branch.&lt;/p&gt;

&lt;p&gt;Vamos deixar os exemplos acima de lado e vamos trabalhar com um exemplo mais simplificado ainda (que tem uma pequena mentirinha explicada melhor no fim desse post). Aqui temos duas branchs (&lt;strong&gt;master&lt;/strong&gt; e &lt;strong&gt;testing&lt;/strong&gt;) e elas tem um ansestral e comum (&lt;em&gt;commit&lt;/em&gt; E).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          A---B---C testing
         /
    D---E---F---G master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se nós estivermos na branch &lt;strong&gt;testing&lt;/strong&gt; e fizermos o comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A árvore da branch testing ficará*:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D---E---F---G---A---B---C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é, o git pegou todo o conteúdo &lt;em&gt;branch&lt;/em&gt; master e, depois dele, colocou o conteúdo da branch testing.&lt;/p&gt;

&lt;p&gt;Um detalhe importante é que se passarmos uma branch ao invés de um commit como parâmetro para o git rebase, então o commit considerado será o commit do topo daquele rebase.&lt;/p&gt;

&lt;p&gt;Na sua forma super-ultra-plus-master-advanced, o rebase vira o rebase interativo. Nessa forma, podemos fazer alterações nos &lt;em&gt;commits&lt;/em&gt; antes de aplicarmos eles. Vamos ver algo essas alterações.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quais são as opções de um rebase interativo?
&lt;/h1&gt;

&lt;p&gt;Para fazermos um rebase interativo, nós precisamos apenas adicionar o parâmetro -i no nosso rebase. Quando fazemos isso, o git irá abrir o editor de texto padrão com um arquivo especial chamado &lt;strong&gt;git-rebase-todo&lt;/strong&gt;. Esse arquivo contém todos os &lt;em&gt;commits&lt;/em&gt; que serão utilizados para o rebase (sendo referenciados pelo seus hashs e suas mensagens de commit) e qual operação que será feita com ele (na parte de exemplos, vamos dar uma olhada na cara desse arquivo).&lt;/p&gt;

&lt;p&gt;Nesse arquivo, nós podemos reordenar os &lt;em&gt;commits&lt;/em&gt;, remover os &lt;em&gt;commits&lt;/em&gt; ou escolher qual operação aplicar. As operações são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;p, pick = utilizar o commit&lt;/li&gt;
&lt;li&gt;r, reword = utilizar o commit, mas alterando a mensagem de commit&lt;/li&gt;
&lt;li&gt;e, edit = utilizar o commit, mas parando para fazer alguma alteração (como adicionar ou remover algum elemento do commit)&lt;/li&gt;
&lt;li&gt;s, squash = utilizar o commit, mas juntar as alterações com o commit anterior (se dois commits alterarem o mesmo arquivo, a alteração mais recente será utilizada)&lt;/li&gt;
&lt;li&gt;f, fixup = semelhante ao squash, mas ignorando a mensagem de commit&lt;/li&gt;
&lt;li&gt;x, exec = executar algum comando shell&lt;/li&gt;
&lt;li&gt;d, drop = remover o commit&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Um pequeno exemplo de como fazer um &lt;em&gt;rebase&lt;/em&gt; para conquistar o coração daquele pichadão/tchutchuca que tá te filmando e quer ser seu namorado
&lt;/h1&gt;

&lt;p&gt;Se você não é a musa do verão, então você precisa ralar para conseguir um bom cobertor de orelhas. E a melhor forma de fazer isso é falar sobre as operações de &lt;em&gt;rebase&lt;/em&gt; do git para aquela pessoa que você está de olho.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwtckygybhb28gzwgrzkr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwtckygybhb28gzwgrzkr.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E pra te dar uma mão nesse plano, vou apresentar aqui um pequeno exemplo de um rebase interativo.&lt;/p&gt;

&lt;p&gt;Imagine a situação, você abriu um &lt;strong&gt;pull request&lt;/strong&gt; e o revisor pediu um monte de alterações. Você &lt;em&gt;comita&lt;/em&gt; as alterações e ele pede outras. Por fim, ele diz "faz um &lt;strong&gt;squash&lt;/strong&gt; e um &lt;strong&gt;push&lt;/strong&gt; aí das alterações para ter um histórico limpo". &lt;/p&gt;

&lt;p&gt;O que ele quer é que todos os &lt;em&gt;commits&lt;/em&gt; do tipo "ajustes do PR" sejam colocados como um único &lt;em&gt;commit&lt;/em&gt; e, se for o caso, alterar a mensagem para representar as alterações feitas. &lt;/p&gt;

&lt;p&gt;Após todas as revisões, o histórico de commits antes do rebase era algo mais ou menos assim:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzqksvs5rx2f7aoznnjgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzqksvs5rx2f7aoznnjgs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como foram feito 6 commits, nós precisamos fazer um rebase interativo à partir de 6 commits anteriores ao ponteiro da HEAD. Fazemos isso com o comando &lt;code&gt;git rebase -i HEAD~6&lt;/code&gt;. &lt;br&gt;
Isso vai abrir a tela de alteração dos &lt;em&gt;commits&lt;/em&gt;. Daí nós só precisamos marcar os &lt;em&gt;commits&lt;/em&gt; que não são o primeiro como &lt;strong&gt;squash&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxg3nv2k84dwuau8urmao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxg3nv2k84dwuau8urmao.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após salvar e fechar, o git vai abrir a tela para nós editarmos a mensagem de &lt;em&gt;commit&lt;/em&gt;. Nessa tela, todas as mensagens de commit que sofreram o &lt;strong&gt;squash&lt;/strong&gt; estarão presentes. Com isso é só colocar a mensagem de commit que você quer e &lt;em&gt;voilá&lt;/em&gt;. No final, a árvore de commits ficará mais ou menos assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjtossbc3e8iqzgaif8oa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjtossbc3e8iqzgaif8oa.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por fim, na hora de devolver as alterações para a branch remota (aka. fazer um push), será necessário usar o parâmetro -f para reescrever o histórico. Ficará assim &lt;code&gt;git push -f&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mais informações legais podem ser encontrados lá na documentação oficial do git (e foi da &lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell#:~:text=A%20branch%20in%20Git%20is,Note" rel="noopener noreferrer"&gt;documentação dos branchs&lt;/a&gt; que eu peguei as imagens usadas)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota: Sendo bem preciosista, os novos *commits&lt;/em&gt; não serão A,B,C mas &lt;em&gt;commits&lt;/em&gt; com mesmas alterações e mensagens de &lt;em&gt;commit&lt;/em&gt;. Porém, o hash será diferente já que o &lt;strong&gt;pai&lt;/strong&gt; do &lt;em&gt;commit&lt;/em&gt; é diferente.&lt;/p&gt;

</description>
      <category>git</category>
      <category>braziliandevs</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Como usar Kafka num projeto Quarkus</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Thu, 03 Dec 2020 16:43:43 +0000</pubDate>
      <link>https://dev.to/lucasscharf/como-usar-kafka-num-projeto-quarkus-5d9c</link>
      <guid>https://dev.to/lucasscharf/como-usar-kafka-num-projeto-quarkus-5d9c</guid>
      <description>&lt;p&gt;Kafka é uma ferramenta muito boa para troca de mensagens entre diferentes aplicações, porém, ele é bem intimidador e com um de detalhes para começar a consumir as mensagens. &lt;/p&gt;

&lt;p&gt;E agora, quem poderá nos defender?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QsSDzdsb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/o7ytg0exznaok9zjq3yq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QsSDzdsb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/o7ytg0exznaok9zjq3yq.jpg" alt="Alt Text" width="500" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  O Que faremos?
&lt;/h1&gt;

&lt;p&gt;Vamos alterar a nossa &lt;a href="https://dev.to/lucasscharf/quarkus-openapi-uma-combinacao-tao-boa-que-deveria-se-chamar-bolo-de-chocolate-4eb7"&gt;gloriosa fábrica de bolo&lt;/a&gt; que já está &lt;a href="https://dev.to/lucasscharf/trabalhando-com-jpa-quarkus-panache-e-bolo-de-chocolate-36k7"&gt;persistindo os dados&lt;/a&gt;. Após fazer a operação será enviado uma mensagem para o broker Kafka com a entidade transformada em JSON.&lt;/p&gt;

&lt;p&gt;Depois disso, por fim de simplicidade, vamos criar um consumidor para essas mensagens no mesmo projeto. Como vamos enviar as mensagens ao broker Kafka é possível consumir essas mensagens em algum outro projeto. &lt;/p&gt;

&lt;p&gt;Para esse artigo é necessário saber um pouco sobre Kafka e ter o feito projeto da &lt;a href="https://dev.to/lucasscharf/trabalhando-com-jpa-quarkus-panache-e-bolo-de-chocolate-36k7"&gt;fábrica de bolo com banco de dados&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  É hora da ação
&lt;/h1&gt;

&lt;p&gt;Caso você não tenha o projeto da fábrica, você pode pegar lá no meu &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/jpa-panache"&gt;git&lt;/a&gt;. Tendo o código em mãos, vamos adicionar as dependências do Kafka e do Jackson (para mandar a mensagem em JSON). Isso é feito colocando o código abaixo na parte de dependências do arquivo &lt;em&gt;pom.xml&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&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.quarkus&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;quarkus-smallrye-reactive-messaging-kafka&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.quarkus&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;quarkus-jackson&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;h2&gt;
  
  
  Escrevendo a mensagem
&lt;/h2&gt;

&lt;p&gt;Vamos começar escrevendo a mensagem. Lá no nosso arquivo BoloResource, vamos adicionar os emitters. O código para isso é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nd"&gt;@Inject&lt;/span&gt; &lt;span class="c1"&gt;//1&lt;/span&gt;
  &lt;span class="nd"&gt;@Channel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"add-bolo"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//2&lt;/span&gt;
  &lt;span class="nc"&gt;Emitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Bolo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;addEmitter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//3&lt;/span&gt;

  &lt;span class="nd"&gt;@Inject&lt;/span&gt;
  &lt;span class="nd"&gt;@Channel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"delete-bolo"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;Emitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deleteEmitter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;@Inject&lt;/code&gt; é utilizado para fazer a inejção do nosso emitter&lt;/li&gt;
&lt;li&gt;O &lt;code&gt;@Channel&lt;/code&gt; vem do import &lt;code&gt;org.eclipse.microprofile.reactive.messaging.Channel&lt;/code&gt; ele é responsável por identificar para onde vamos enviar as mensagens e configurar tudo corretamente (vamos ver mais sobre a configuração lá pra frente)&lt;/li&gt;
&lt;li&gt;A classe Emitter vem do import &lt;code&gt;org.eclipse.microprofile.reactive.messaging.Emitter&lt;/code&gt; e é ele quem envia a mensagem para o Kafka*&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O Envio de mensagem é feito através do método &lt;a href="https://smallrye.io/smallrye-reactive-messaging/2.0.1/apidocs/org/eclipse/microprofile/reactive/messaging/Emitter.html"&gt;Emitter#send&lt;/a&gt;. Vamos alterar BoloResource adicionando  esse método logo antes do return. O código vai ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nd"&gt;@POST&lt;/span&gt;
  &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Bolo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bolo&lt;/span&gt; &lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//coisa feia, não façam isso em casa&lt;/span&gt;
    &lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;addEmitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@DELETE&lt;/span&gt;
  &lt;span class="nd"&gt;@Path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{nome}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Bolo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Bolo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"nome"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;deleteEmitter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//2&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Bolo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Estamos enviando para o kafka todo o bolo&lt;/li&gt;
&lt;li&gt;Estamos enviando para o kafka apenas o nome do bolo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Além disso, é necessário descrever e envio de mensagens no arquivo &lt;em&gt;application.properties&lt;/em&gt;. Para tanto, basta adicionar as seguintes linhas nele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;mp.messaging.outgoing.add-bolo.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.outgoing.add-bolo.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;add-bolo&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.outgoing.add-bolo.value.serializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;io.quarkus.kafka.client.serialization.ObjectMapperSerializer&lt;/span&gt;

&lt;span class="py"&gt;mp.messaging.outgoing.delete-bolo.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.outgoing.delete-bolo.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;delete-bolo&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.outgoing.delete-bolo.value.serializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.apache.kafka.common.serialization.StringSerializer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todas as configurações tem o mesmo formato &lt;code&gt;mp.messaging.outgoing.&amp;lt;nome do canal&amp;gt;.&amp;lt;nome da propriedade&amp;gt;&lt;/code&gt;. As propriedades que nós definimos servem para dizer que vamos nos comunicar com Kafka e que vamos serializar a mensagem mensagem como JSON usando o Jackson ou enviando uma String normal. &lt;br&gt;
&lt;a href="https://docs.confluent.io/platform/current/installation/configuration/producer-configs.html"&gt;Qualquer propriedade&lt;/a&gt; dos produtores do kafka podem ser utilizados. &lt;/p&gt;
&lt;h2&gt;
  
  
  Lendo a mensagem
&lt;/h2&gt;

&lt;p&gt;A classe abaixo pode estar tanto no mesmo projeto quanto em um outro projeto (desde que tenha as dependências corretas).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.enterprise.context.ApplicationScoped&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.eclipse.microprofile.reactive.messaging.Incoming&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ApplicationScoped&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;BoloKafkaConsumer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Incoming&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"add-bolo-consumer"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consumeAdd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bolo adicionado: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bolo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Incoming&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"delete-bolo-consumer"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consumeDelete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nome do bolo deletado: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os dois métodos recebem o JSON do Bolo e escrevem na saída padrão. Notem que, apesar de termos enviado o bolo como objeto, estamos lendo como String. É possível configurar para receber um Bolo ou fazer qualquer transformação que seja interessante para nós. &lt;/p&gt;

&lt;p&gt;Assim como no envio, também temos que configurar a leitura no &lt;em&gt;application.properties&lt;/em&gt;. Isso pode ser feito através do código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;mp.messaging.incoming.add-bolo-consumer.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.add-bolo-consumer.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;add-bolo&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.add-bolo-consumer.value.deserializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;

&lt;span class="py"&gt;mp.messaging.incoming.delete-bolo-consumer.connector&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smallrye-kafka&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.delete-bolo-consumer.topic&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;delete-bolo&lt;/span&gt;
&lt;span class="py"&gt;mp.messaging.incoming.delete-bolo-consumer.value.deserializer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;org.apache.kafka.common.serialization.StringDeserializer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semelhante ao produtor, no consumidor as propriedades tem o formato &lt;code&gt;mp.messaging.outgoing.&amp;lt;nome do canal&amp;gt;.&amp;lt;nome da propriedade&amp;gt;&lt;/code&gt; e todas as propriedades podem ser encontradas no site da &lt;a href="https://docs.confluent.io/platform/current/installation/configuration/consumer-configs.html"&gt;confluent&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparar para rodar
&lt;/h2&gt;

&lt;p&gt;Para rodar essa aplicação, nós vamos precisar do &lt;a href="https://docs.docker.com/compose/"&gt;docker-compose&lt;/a&gt;. Para isso, basta usar o seguinte arquivo docker-compose.yml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:12-alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sarah&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Connor&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;skynet&lt;/span&gt;
  &lt;span class="na"&gt;zookeeper&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;strimzi/kafka:0.19.0-kafka-2.5.0&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sh"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bin/zookeeper-server-start.sh&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;config/zookeeper.properties"&lt;/span&gt;
    &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2181:2181"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;LOG_DIR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/logs&lt;/span&gt;

  &lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;strimzi/kafka:0.19.0-kafka-2.5.0&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sh"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bin/kafka-server-start.sh&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;config/server.properties&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--override&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;listeners=$${KAFKA_LISTENERS}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--override&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;advertised.listeners=$${KAFKA_ADVERTISED_LISTENERS}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--override&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;zookeeper.connect=$${KAFKA_ZOOKEEPER_CONNECT}"&lt;/span&gt;
    &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;zookeeper&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9092:9092"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;LOG_DIR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/tmp/logs"&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_ADVERTISED_LISTENERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAINTEXT://localhost:9092&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_LISTENERS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PLAINTEXT://0.0.0.0:9092&lt;/span&gt;
      &lt;span class="na"&gt;KAFKA_ZOOKEEPER_CONNECT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zookeeper:2181&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse docker-compose.yml instância e configura um banco de dados, o kafka e o zookeeper (que é um requisito para o Kafka funcionar). &lt;/p&gt;

&lt;h2&gt;
  
  
  Hora do teste
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6c51HVma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/71nxc1jpg0rj5vaea7r4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6c51HVma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/71nxc1jpg0rj5vaea7r4.jpg" alt="Alt Text" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de levantar o docker-compose (&lt;code&gt;docker-compose up&lt;/code&gt; no mesmo diretório que está o arquivo docker-compose.yml), levantar o projeto (&lt;code&gt;mvn quarkus:dev&lt;/code&gt; no diretório base do projeto), entrar na url &lt;a href="http://localhost:8080/swagger-ui"&gt;http://localhost:8080/swagger-ui&lt;/a&gt; e fazer a cadastro de um bolo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DrQB30jC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/ig2p7d8h6nhhmipdofu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DrQB30jC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/ig2p7d8h6nhhmipdofu4.png" alt="Alt Text" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de apertar o botão do execute. É só olhar no terminal e vamos ver a saída da aplicação:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VgW9aNzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/xi7cdre96en0y8yi0nhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VgW9aNzJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/xi7cdre96en0y8yi0nhu.png" alt="Alt Text" width="800" height="20"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E é isso, agora é possível brincar enviando novos bolos, excluíndo, etc...&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Nossa &lt;a href="https://dev.to/lucasscharf/quarkus-openapi-uma-combinacao-tao-boa-que-deveria-se-chamar-bolo-de-chocolate-4eb7"&gt;fábrica de bolo&lt;/a&gt; que já &lt;a href="https://dev.to/lucasscharf/trabalhando-com-jpa-quarkus-panache-e-bolo-de-chocolate-36k7"&gt;salva as coisas no banco de dados&lt;/a&gt; está evoluindo e está se comunicando via mensagens &amp;lt;3&lt;/p&gt;

&lt;p&gt;Nos próximos episódios, vamos garantir a atualização de banco de dados com flyway, adicionar rastreabilidade, resiliência e mais um monte de coisa massa =D&lt;/p&gt;

&lt;p&gt;Outra coisa muito massa é que conseguimos enviar mensagens para o MQTT, AMQP ou JMS sem mexer no código. Só ajustando o &lt;em&gt;pom.xml&lt;/em&gt; e o &lt;em&gt;application.properties&lt;/em&gt;. Isso é mesmo é algo supimpa. &lt;/p&gt;

&lt;p&gt;Ah, e o código desse post pode ser encontrado no &lt;a href="https://github.com/lucasscharf/blog-posts-code/tree/master/kafka-consumer-emitter"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;*Na realidade, ele a função do emitter é colocar a mensagem dentro de um fluxo reativo do Smallrye. O Smallrye possui um conector que acaba fazendo o processo de enviar a mensagem para o kafka. Porém, é possível utilizar esses fluxos sem enviar para o kafka ou para qualquer outro broker de mensageria. &lt;/p&gt;

</description>
      <category>kafka</category>
      <category>quarkus</category>
      <category>java</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Alguns dos principais comandos do git</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Fri, 09 Oct 2020 02:24:59 +0000</pubDate>
      <link>https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd</link>
      <guid>https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd</guid>
      <description>&lt;p&gt;Seja bem vindo a mais uma ~gentil~ introdução ao git e hoje nós vamos conhecer alguns dos principais comandos que nós usamos. &lt;br&gt;
Antes de começar, vamos lembrar do nosso planejamento de posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;O que é o GIT e como usar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Principais comandos do git  ⟵ você está aqui&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;Como fazer um rebase de presença&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj"&gt;Como escrever um README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e"&gt;Boas práticas para utilizar o git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Quais comandos vamos estudar?
&lt;/h1&gt;

&lt;p&gt;Atualmente, o git possui 137 comandos e uma quantidade infinita de parâmetros, configurações, etc...&lt;br&gt;
Infelizmente, não dá para falar tudo em menos de mil palavras, então selecionei os mais comuns para falar sobre. &lt;/p&gt;

&lt;p&gt;Caso você queira se aprofundar mais, é só dar uma olhada na &lt;a href="https://git-scm.com/docs" rel="noopener noreferrer"&gt;documentação oficial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Os comandos que vamos estudar são: clone, add, reset, commit, checkout, push e pull.&lt;/p&gt;

&lt;p&gt;Então, vocês estão prontas crianças?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft1wxtlny670khcy6oc5x.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft1wxtlny670khcy6oc5x.jpeg" alt="Alt capitão bob sponja"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Clone
&lt;/h1&gt;

&lt;p&gt;O primeiro comando que nós temos é o &lt;strong&gt;clone&lt;/strong&gt;. Ele tem a função de copiar o repositório remoto (que geralmente está armazenado no &lt;a href="http://github.com/" rel="noopener noreferrer"&gt;github&lt;/a&gt;, &lt;a href="http://bitbucket.org/" rel="noopener noreferrer"&gt;bitbucket&lt;/a&gt; ou &lt;a href="https://gitlab.com/explore" rel="noopener noreferrer"&gt;gitlab&lt;/a&gt;) para a sua máquina. A forma mais comum desse comando é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone &amp;lt;URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o conteúdo da URL é o caminho para o repositório remoto.&lt;/p&gt;

&lt;p&gt;Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/lucasscharf/blog-posts-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fazendo isso, o git vai criar um diretório com o nome igual ao do repositório (no caso do exemplo será blog-posts-code) e copiar todo o conteúdo do repositório remoto para o local.&lt;/p&gt;

&lt;h1&gt;
  
  
  Add
&lt;/h1&gt;

&lt;p&gt;Você se lembra lá do outro post que nós falamos sobre as áreas do git? Se não lembra, &lt;a href="https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf"&gt;corre lá&lt;/a&gt; que eu te espero.&lt;/p&gt;

&lt;p&gt;O comando &lt;strong&gt;add&lt;/strong&gt; tem a seguinte cara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add &amp;lt;caminho para o diretório ou arquivo&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele faz com que os arquivos que não estavam na área de estagiamento passem a fazer parte da área da estagiamento*. &lt;/p&gt;

&lt;p&gt;O git é extremamente versátil na hora de indicar o caminho para o &lt;strong&gt;add&lt;/strong&gt;. &lt;br&gt;
Abaixo temos alguns exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;#Adiciona um arquivo
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;AlgumaClasse.java&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona um diretório*
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;AlgumDiretório&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona um diretório* com uma barra
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;AlgumDiretório/&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona todos os arquivos e diretórios* que estão abaixo do diretório local
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona o conteúdo interno de um diretório (e por consequência o diretório)
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;AlgumDiretório/Algum_conteúdo_interno&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona vários arquivos e diretórios* num mesmo comando
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;Classe1.java&lt;/span&gt; &lt;span class="err"&gt;Classe2.java&lt;/span&gt; &lt;span class="err"&gt;Diretório3&lt;/span&gt;

&lt;span class="c"&gt;#Adiciona arquivos com os caracteres coringa
&lt;/span&gt;&lt;span class="err"&gt;git&lt;/span&gt; &lt;span class="err"&gt;add&lt;/span&gt; &lt;span class="err"&gt;*.java&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Reset
&lt;/h1&gt;

&lt;p&gt;O &lt;strong&gt;reset&lt;/strong&gt; é o irmão gêmeo do mal do &lt;strong&gt;add&lt;/strong&gt;. Enquanto o &lt;strong&gt;add&lt;/strong&gt; adiciona um diretório na área de estagiamento, o &lt;strong&gt;reset&lt;/strong&gt; tira.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdizizj29j687vvh4i12.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdizizj29j687vvh4i12.jpg" alt="Alt Paola Brach"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Além disso, o &lt;strong&gt;reset&lt;/strong&gt; tem uma versão anabolizada que é o &lt;code&gt;reset --hard&lt;/code&gt;. Que não somente retira os arquivos da área de estagiamento como também excluí os mesmos.&lt;/p&gt;

&lt;p&gt;A sintaxe do comando de &lt;strong&gt;reset&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;git reset [--hard] [commit]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O no commit, você coloca o &lt;strong&gt;hash&lt;/strong&gt; do commit. Você também pode utilizar atalhos commit &lt;code&gt;HEAD~1&lt;/code&gt; para pegar o último commit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Commit
&lt;/h1&gt;

&lt;p&gt;Após usarmos o &lt;code&gt;git add&lt;/code&gt; para levar as mudanças do diretório de trabalho para a área de estagiamento, nós usamos o comando &lt;strong&gt;commit&lt;/strong&gt; para levar os arquivos para o repositório local. A sintaxe do commit é mais fácil do que andar pra frente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E é só isso. Após o enter, o git abrirá o seu editor de texto favorito para você escrever a mensagem de commit. &lt;br&gt;
É EXTREMAMENTE importante escrever uma mensagem ou o &lt;em&gt;commit&lt;/em&gt; não será realizado.&lt;/p&gt;
&lt;h1&gt;
  
  
  Branch
&lt;/h1&gt;

&lt;p&gt;O comando &lt;code&gt;git branch&lt;/code&gt; permite criar, listar ou deletar as &lt;em&gt;branchs&lt;/em&gt;**. Suas três principais formas são:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git branch
git branch &amp;lt;nome_da_branch&amp;gt;
git branch -D &amp;lt;nome_da_branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O primeiro comando lista todas as &lt;em&gt;branchs&lt;/em&gt; existentes no repositório local. &lt;br&gt;
O segundo vai criar uma &lt;em&gt;branch&lt;/em&gt; com o nome que nós passamos por parâmetro.&lt;br&gt;
E o terceiro vai deletar a &lt;em&gt;branch&lt;/em&gt; com o nome passado por parâmetro. &lt;/p&gt;

&lt;p&gt;É importante notar que os nomes de branch não podem ter espaços.&lt;/p&gt;
&lt;h1&gt;
  
  
  Checkout
&lt;/h1&gt;

&lt;p&gt;O &lt;strong&gt;checkout&lt;/strong&gt; serve para movimentar entre diferentes &lt;em&gt;branchs&lt;/em&gt; de desenvolvimento. A sintaxe é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout &amp;lt;nome_da_branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supondo que tenhamos uma &lt;em&gt;branch&lt;/em&gt; chamada meu_exemplo, então, nós podemos usar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout meu_exemplo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todos os &lt;em&gt;commits&lt;/em&gt; que estavam salvos na &lt;em&gt;branch&lt;/em&gt; anterior sumirão e, no lugar, vão surgir os commits da &lt;em&gt;branch&lt;/em&gt; meu_exemplo. E o nosso diretório de trabalho vai se referência à &lt;em&gt;branch&lt;/em&gt; meu_exemplo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Push
&lt;/h1&gt;

&lt;p&gt;O &lt;em&gt;push&lt;/em&gt; é a última parte do processo. Ele envia as  alterações do repositório local para o repositório remoto.*&lt;/p&gt;

&lt;p&gt;A sintaxe é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Pull
&lt;/h1&gt;

&lt;p&gt;O &lt;strong&gt;pull&lt;/strong&gt; é um comando* bem simples que atualiza o diretório local com o conteúdo do repositório remoto.&lt;br&gt;
Esse é outro comando tão fácil quanto andar pra frente. A sintaxe é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Foi uma tarefa difícil escolher apenas alguns comandos para listar. É bem provável que eu faça uma parte 2 e uma parte 3 para esses comandos, mas isso é algo para o futuro.&lt;br&gt;
Foi ainda mais difícil tentar não falar todas as coisas legais que o git faz para executar esses comandos. Mas é isso. No próximo post, vamos falar sobre um assunto que eu gosto muito que é como fazer um rebase de presença.&lt;/p&gt;

&lt;p&gt;*Isso é uma meia verdade. Nos comentários eu explico um pouco mais detalhado sobre o que acontece. É possível seguir uma vida tranquila sem olhar para os comentários.&lt;/p&gt;

&lt;p&gt;** Pensem numa &lt;em&gt;branch&lt;/em&gt; como uma linha de desenvolvimento que tem todos os &lt;em&gt;commits&lt;/em&gt; feitos.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>ptbr</category>
      <category>git</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Uma gentil introdução ao git e seus comandos</title>
      <dc:creator>Aleatório</dc:creator>
      <pubDate>Sat, 03 Oct 2020 09:49:59 +0000</pubDate>
      <link>https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf</link>
      <guid>https://dev.to/lucasscharf/uma-gentil-introducao-ao-git-e-seus-comandos-2lf</guid>
      <description>&lt;p&gt;10 em cada 10 desenvolvedores recomendam a utilização do git como ferramenta de controle de versão. &lt;/p&gt;

&lt;p&gt;Ao longo de todos esses anos, o git tem ajudado desenvolvedores ao redor do mundo a organizarem seus projetos, fazerem backups, trocarem informações, escreverem livros, montarem blogs, etc... Porém, apesar de ser uma ferramenta tão incrível muita gente acaba usando sem saber exatamente o que tá fazendo, dependendo da IDE e passando por algumas dificuldades sem necessidade. &lt;/p&gt;

&lt;p&gt;E é por isso que eu resolvi fazer uma sequência de posts falando sobre o git e como usar. Esses posts serão divididos nas seguintes partes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que é o GIT e como usar &lt;strong&gt;⟵ você está aqui&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/alguns-dos-principais-comandos-do-git-3dhd"&gt;Principais comandos do git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-fazer-um-rebase-de-presenca-2jj7"&gt;Como fazer um rebase de presença&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/como-escrever-um-readme-md-26jj"&gt;Como escrever um README.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/lucasscharf/boas-praticas-para-usar-o-git-2e0e"&gt;Boas práticas para utilizar o git&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  O que é esse tal git?
&lt;/h1&gt;

&lt;p&gt;Também conhecido como melhor invenção desde &lt;a href="https://www.google.com/search?q=aquela+paradinha+pra+co%C3%A7ar+as+costas&amp;amp;oq=aquela+paradinha+pra+co%C3%A7ar+as+costas&amp;amp;aqs=chrome..69i57.4901j0j9&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8" rel="noopener noreferrer"&gt;aquela paradinha para coçar as costas&lt;/a&gt;. O &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;git&lt;/a&gt; é uma ferramenta livre, de código aberto para controle de versão distribuído. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1w2hh3b8438x6ok24qbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1w2hh3b8438x6ok24qbv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com ele o código e suas alterações ficam nas máquinas de todos os usuários. Através da utilização de &lt;em&gt;snapshots&lt;/em&gt; dos arquivos, é possível ter acesso rápido a tudo o que foi feito pelo resto do time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Como funciona?
&lt;/h1&gt;

&lt;p&gt;Antes de entrar nos detalhes de como o git funciona, é necessário entender que o git trabalha com 4 áreas diferentes. O diretório de trabalho (&lt;em&gt;working directory&lt;/em&gt;), a área de estagiamento (&lt;em&gt;staging area&lt;/em&gt;), o repositório local (&lt;em&gt;local repo&lt;/em&gt;) e o repositório remoto (&lt;em&gt;remote repo&lt;/em&gt;). Essas áreas vão se relacionando entre si, mais ou menos como na imagem abaixo. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzbu0eocercv8edfs846m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzbu0eocercv8edfs846m.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Diretório de trabalho&lt;/strong&gt; é o diretório que você está utilizando para trabalhar (duh!). Não vou entrar muito nos detalhes (já que essa é uma introdução gentil), mas pense no diretório de trabalho como um &lt;a href="http://www.otimizacao-sites-busca.com/otpo/posicionamento/sandbox-caixa-areia.htm#:~:text=Sandbox%20foi%20usado%20primeiramente%20%E2%80%93%20e,evitar%20danos%20ao%20pr%C3%B3prio%20programa" rel="noopener noreferrer"&gt;sandbox&lt;/a&gt; para todas as alterações que você está fazendo. Ele permite que você faça/desfaça alterações sem compromisso ou afetar qualquer outra coisa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Área de estagiamento&lt;/strong&gt; essa área é o meio termo entre o seu diretório de trabalho e o repositório local. Nesse momento, as alterações estão indicadas para serem salvas no repostório local, porém ainda não foram salvas. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repositório local&lt;/strong&gt; é onde as coisas ficam salvas. Todos arquivos que você cria e as alterações desses arquivos ficam salvas de forma compactada dentro do diretório .git.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repositório remoto&lt;/strong&gt; é um local que centraliza os repositórios seus e de todas as pessoas envolvidas no projeto. Os repositórios mais remotos que nós temos são o &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;github&lt;/a&gt;, o &lt;a href="http://bitbucket.org/" rel="noopener noreferrer"&gt;bitbucket&lt;/a&gt; e o &lt;a href="https://gitlab.com/explore" rel="noopener noreferrer"&gt;gitlab&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Entendendo esses conceitos, fica mais fácil de entender como funcionam alguns comandos do git.&lt;/p&gt;

&lt;p&gt;Nós criamos um repositório através do comando &lt;code&gt;git init&lt;/code&gt; (esse comando cria o repostório local, a área de estagiamento e o diretório de trabalho);&lt;br&gt;
Quando nós alteramos um arquivo, nós estamos alterando o diretório de trabalho;&lt;br&gt;
Para persistir essa alteração, nós usamos o comando &lt;code&gt;git add&lt;/code&gt;;&lt;br&gt;
Para levar essa alteração da área de estagiamento para o repositório local, é utilizado o comando &lt;code&gt;git commit&lt;/code&gt;;&lt;br&gt;
o processo de levar o conteúdo do repositório local para o repositório remoto, é feito com o comando &lt;code&gt;git push&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E nós temos o caminho de volta, onde o &lt;code&gt;git clone&lt;/code&gt; copia o repositório remoto e inicializa esse repositório (com a área de estagiamento e diretório de trabalho) num diretório específico;&lt;br&gt;
O &lt;code&gt;git fetch&lt;/code&gt; atualiza o repositório local com as informações do repositório remoto;&lt;br&gt;
O &lt;code&gt;git merge&lt;/code&gt; atualiza o diretório local com as mudanças feitas no diretório remoto. (nos próximos posts vou falar melhor sobre o pull e checkout).&lt;/p&gt;

&lt;p&gt;Imagino que já deva ter ficado claro nesse momento, mas é bom frisar:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O GIT É A FERRAMENTA DE CONTROLE DE VERSÃO, GITHUB/GITLAB/BITBUCKET PERMITEM O ARMAZENAMENTO DE REPOSITÓRIO REMOTOS.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;Espero do fundo do coração ter conseguido explicar de forma simples como as coisas funcionam. Inicialmente, eu iria fazer um único post, mas é tanta coisa legal para falar que fica complicado :/&lt;br&gt;
Se tem algum tema legal sobre desenvolvimento que você queira que eu fale sobre, deixe um comentário. Você fará um aleatório muito feliz. &lt;/p&gt;

</description>
      <category>git</category>
      <category>ptbr</category>
      <category>beginners</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
