<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Víctor Fructuoso</title>
    <description>The latest articles on Forem by Víctor Fructuoso (@fructuoso).</description>
    <link>https://forem.com/fructuoso</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%2F512970%2F8503d594-d598-4c67-8d4a-f388b74aaa65.PNG</url>
      <title>Forem: Víctor Fructuoso</title>
      <link>https://forem.com/fructuoso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fructuoso"/>
    <language>en</language>
    <item>
      <title>Criando um CRUD do ZERO em .NET usando o Liquid Framework</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Tue, 16 Aug 2022 23:29:40 +0000</pubDate>
      <link>https://forem.com/fructuoso/criando-um-crud-do-zero-em-net-usando-o-liquid-framework-af9</link>
      <guid>https://forem.com/fructuoso/criando-um-crud-do-zero-em-net-usando-o-liquid-framework-af9</guid>
      <description>&lt;p&gt;O &lt;a href="https://github.com/Avanade/Liquid-Application-Framework" rel="noopener noreferrer"&gt;Liquid&lt;/a&gt; é um framework Open Source desenvolvido pela Avanade, para acelerar o desenvolvimento de aplicações cloud-native em .NET.&lt;/p&gt;

&lt;p&gt;Neste artigo, serão utilizadas apenas ferramentas de linha de comando e todos os passos podem ser realizados em qualquer setup que seja compatível com o dotnet (inclusive o artigo foi elaborado usando o WSL2 com Ubuntu)&lt;/p&gt;

&lt;p&gt;Para a construção do nosso CRUD vamos começar instalando o Liquid.Templates, que irá nos apoiar no processo de criação do projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pré-Requisitos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;.NET 5 (no momento em que este artigo foi escrito esta era a versão mais recente do .NET compatível com o Liquid)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Instalando o Liquid.Templates
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new &lt;span class="nt"&gt;-i&lt;/span&gt; Liquid.Templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso você já possua o Liquid.Templates instalado, recomendo a atualização do mesmo, para garantir que estamos trabalhando com a versão mais atual.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new &lt;span class="nt"&gt;--update-apply&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ter certeza que o Liquid.Templates foi instalado com sucesso vamos executar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new Liquid &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Como explorar o Liquid.Templates
&lt;/h2&gt;

&lt;p&gt;Caso o template tenha sido instalado corretamente, você deverá ter um retorno semelhante ao apresentado 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%2Fuploads%2Farticles%2Fd4h2x94thnzyryr42ybo.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%2Fd4h2x94thnzyryr42ybo.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na imagem acima, temos a relação de todos os templates que foram instalados com uma breve descrição de cada um deles.&lt;/p&gt;

&lt;p&gt;Para este artigo utilizaremos o liquidcrudextsolution.&lt;/p&gt;

&lt;p&gt;Vamos então explorar os parâmetros esperados para este template através do comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new liquidcrudextsolution &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Será apresentada a seguinte tela:&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%2F2s8m457x57fhqj3ayx0e.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%2F2s8m457x57fhqj3ayx0e.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para este template são esperados os seguintes parâmetros:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parâmetro&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;projectName&lt;/td&gt;
&lt;td&gt;Namespace da Solution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;entityName&lt;/td&gt;
&lt;td&gt;Nome da Entidade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;entityIdType&lt;/td&gt;
&lt;td&gt;Tipo do Id da Entidade&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Para começar o processo de criação do micro serviço, vamos criar um diretório chamado "catalogo" e vamos entrar no diretorio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;catalogo
&lt;span class="nb"&gt;cd &lt;/span&gt;catalogo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Realizando SETUP do Projeto
&lt;/h2&gt;

&lt;p&gt;Neste exemplo o microserviço será chamado "Fructuoso.Exemplo.Catalogo", minha entidade será Produto e o tipo do Id será Guid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new liquidcrudextsolution &lt;span class="nt"&gt;-p&lt;/span&gt; Fructuoso.Exemplo.Catalogo &lt;span class="nt"&gt;-e&lt;/span&gt; Produto &lt;span class="nt"&gt;-en&lt;/span&gt; Guid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após executar o comando acima, a seguinte estrutura de pastas será criada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦src
 ┣ 📂Fructuoso.Exemplo.Catalogo.Domain
 ┃ ┣ 📂Entities
 ┃ ┃ ┗ 📜ProdutoEntity.cs
 ┃ ┣ 📜Fructuoso.Exemplo.Catalogo.Domain.csproj
 ┃ ┗ 📜IDomainInjection.cs
 ┣ 📂Fructuoso.Exemplo.Catalogo.WebApi
 ┃ ┣ 📂Controllers
 ┃ ┃ ┗ 📜ProdutoController.cs
 ┃ ┣ 📜Fructuoso.Exemplo.Catalogo.WebApi.csproj
 ┃ ┣ 📜Program.cs
 ┃ ┣ 📜Startup.cs
 ┃ ┗ 📜appsettings.json
 ┗ 📜Fructuoso.Exemplo.Catalogo.Microservice.sln
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Antes de seguir, é necessário restaurar as dependêcias da solução. (Em alguns casos sua IDE pode sugerir fazer isso automáticamente para você)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;src
dotnet restore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conhecendo a estrutura da solução
&lt;/h2&gt;

&lt;p&gt;O template escolhido criará automaticamente dois projetos &lt;strong&gt;WebAPI&lt;/strong&gt; e &lt;strong&gt;Domain&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebAPI
&lt;/h3&gt;

&lt;p&gt;Neste projeto ficam os &lt;em&gt;controllers&lt;/em&gt; e toda a injeção de dependência necessaria, sendo que parte dela já foi criada automaticamente pelo template do Liquid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain
&lt;/h3&gt;

&lt;p&gt;Neste projeto fica toda a regra de negócio necessária para o funcionamento do micro serviço, como estamos utilizando o Liquid CRUD Extension, a regra necessária para a criação de um CRUD básico fica totalmente encapsulada.&lt;/p&gt;

&lt;p&gt;Nos próximos artigos veremos como estender esses comportamentos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação
&lt;/h2&gt;

&lt;p&gt;Depois de explorar um poouco o código gerado automaticamente pelo template é possivel notar que temos 2 TODO para implementar e com a implementação desses dois blocos de código teremos nosso CRUD 100% funcional.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entidade (ProdutoEntity)
&lt;/h3&gt;

&lt;p&gt;Neste primeiro TODO precisamos apenas definir quais propriedades serão utilizadas.&lt;/p&gt;

&lt;p&gt;Para este exemplo vamos criar apenas Código, Nome e Preço.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProdutoEntity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LiquidEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Codigo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Nome&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Preco&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Startup
&lt;/h3&gt;

&lt;p&gt;A classe Startup.cs é responsável pela configuração da nossa WebAPI, seguiremos com o passo a passo sugerido pelo TODO gerado pelo template. Neste artigo faremos uso do InMemory do &lt;strong&gt;Entity Framework&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vamos criar o projeto &lt;strong&gt;Repository&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new liquiddbcontextproject &lt;span class="nt"&gt;--projectName&lt;/span&gt; Fructuoso.Exemplo.Catalogo &lt;span class="nt"&gt;--entityName&lt;/span&gt; Produto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Adicione o projeto &lt;strong&gt;Repository&lt;/strong&gt; na solução.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet sln add Fructuoso.Exemplo.Catalogo.Repository/Fructuoso.Exemplo.Catalogo.Repository.csproj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Restaure as dependências do projeto novamente
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet restore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Adicione o projeto &lt;strong&gt;Repository&lt;/strong&gt; como referência ao projeto &lt;strong&gt;WebAPI&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;Fructuoso.Exemplo.Catalogo.WebApi 
dotnet add reference ../Fructuoso.Exemplo.Catalogo.Repository/Fructuoso.Exemplo.Catalogo.Repository.csproj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Adicione o pacote &lt;strong&gt;Microsoft.EntityFrameworkCore.InMemory&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Microsoft.EntityFrameworkCore.InMemory &lt;span class="nt"&gt;--version&lt;/span&gt; 5.0.13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Importe a referência do &lt;strong&gt;EntityFrameworkCore&lt;/strong&gt; nesta classe
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configure o DbContextOptions incluíndo o seguinte código abaixo do TODO (este passo determina o banco de dados que será utilizado pela aplicação)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DbContextOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseInMemoryDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CRUD"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Adicione o pacote &lt;strong&gt;Liquid.Repository.EntityFramework&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Liquid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EntityFramework&lt;/span&gt; &lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Importe a referência do &lt;strong&gt;Liquid.Repository.EntityFramework.Extensions&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Liquid.Repository.EntityFramework.Extensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Importe a referência do Repository nesta classe
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Fructuoso.Exemplo.Catalogo.Repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Registre o DbContext no &lt;strong&gt;ServiceCollection&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddLiquidEntityFramework&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LiquidDbContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProdutoEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Executando aplicação
&lt;/h2&gt;

&lt;p&gt;Com o CRUD completamente implementado é hora de executar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por padrão a aplicação rodará nas portas 5000 (http) e 5001 (https), ao acessar o endereço &lt;a href="https://localhost:5001/swagger" rel="noopener noreferrer"&gt;https://localhost:5001/swagger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deverá ser apresentada uma tela como esta:&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%2Ffqtvl2d64qeqy4nb60bw.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%2Ffqtvl2d64qeqy4nb60bw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Encerramento
&lt;/h2&gt;

&lt;p&gt;Como foi possível perceber, para criar um CRUD foi preciso apenas determinar as propriedades da nossa entidade e definir qual o repositório que será utilizado todo o restante do trabalho foi gerado automaticamente. &lt;/p&gt;

&lt;p&gt;Por hoje é isso, se você curtiu esse artigo não esqueça de deixar seu like e fique ligado nos proximos posts com mais conteudo sobre o Liquid Framework.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>backend</category>
      <category>csharp</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Melhorando o tratamento de exceções no C#</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Thu, 02 Dec 2021 14:50:22 +0000</pubDate>
      <link>https://forem.com/fructuoso/melhorando-o-tratamento-de-excecoes-no-c-fk3</link>
      <guid>https://forem.com/fructuoso/melhorando-o-tratamento-de-excecoes-no-c-fk3</guid>
      <description>&lt;p&gt;Um dos meus principais lemas como programador é:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Se você precisar debugar o código para achar um BUG, é por que o código não está bem escrito.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Neste artigo, abordo três formas de relançar uma exceção e quais as principais diferências entre elas.&lt;/p&gt;

&lt;p&gt;Antes de falar sobre a Exception em si, precisamos entender a propriedade mais importante que ela tem... (pausa dramática)&lt;/p&gt;

&lt;h3&gt;
  
  
  StackTrace
&lt;/h3&gt;

&lt;p&gt;Esta certamente é a propriedade mais importante de qualquer Exception, pois através dela é possível entender toda a "pilha de chamadas" que foi realizada, até o exato ponto onde a exceção foi lançada.&lt;/p&gt;

&lt;p&gt;Daí chegamos ao ponto que muitos programadores iniciantes costumam errar...&lt;/p&gt;

&lt;p&gt;É muito comum ver tratamentos de erro com algo mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_logger.LogError(ex.Message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Quando isso é feito, estamos jogando fora praticamente toda e qualquer informação que pode nos ajudar a rastrear o erro através do Log.&lt;/p&gt;

&lt;p&gt;Neste caso, o ideal seria utilizar algo como o código abaixo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_logger.LogError(ex, ex.Message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Neste &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.loggerextensions.logerror?view=dotnet-plat-ext-6.0&amp;amp;viewFallbackFrom=net-6.0"&gt;link&lt;/a&gt; temos a documentação oficial da Microsoft com todas as implementações do método de extensão LogError da interface ILogger.&lt;/p&gt;

&lt;p&gt;Caso você precise obter os dados da exceção para usar em algum outro local, é preferível ainda usar o ToString(), que entrega o Message concatenado com o StackTrace, fornecendo assim, um detalhamento completo do erro.&lt;/p&gt;
&lt;h2&gt;
  
  
  O cenário
&lt;/h2&gt;

&lt;p&gt;Para ilustrar as três formas que serão abordadas, vamos entender o seguinte cenário:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;A ClasseB possuí o método "OutroMetodo" não implementado.&lt;br&gt;
A ClasseA possui o método "UmMetodo" que chama o método da ClasseB, que por sua vez lançará a exceção "NotImplementedException".&lt;/p&gt;

&lt;p&gt;Veremos as três formas de implementar o tratamento de exceção na ClasseA, e o impacto de cada uma delas no Log da aplicação.&lt;/p&gt;
&lt;h3&gt;
  
  
  throw
&lt;/h3&gt;

&lt;p&gt;Neste caso, a exceção é relançada mantendo o StackTrace completo.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Resultado:&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;System.NotImplementedException: The method or operation is not implemented.
   at ClasseB.OutroMetodo() in Program.cs:line 23
   at ClasseA.UmMetodo() in Program.cs:line 12
   at Program.&amp;lt;Main&amp;gt;$(String[] args) in Program.cs:line 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  throw ex
&lt;/h3&gt;

&lt;p&gt;Nesta situação a exceção é relançada, mas diferentemente do cenário anterior o StackTrace do que aconteceu antes deste relançamento é descartado.&lt;/p&gt;

&lt;p&gt;Em alguns casos isso pode ser útil, para  que possamos ocultar algum detalhe do componente ou até mesmo tornar o log menor e mais objetivo.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Notem que neste caso, nenhuma referência a ClasseB é feita.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultado:&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;System.NotImplementedException: The method or operation is not implemented.
   at ClasseA.UmMetodo() in Program.cs:line 17
   at Program.&amp;lt;Main&amp;gt;$(String[] args) in Program.cs:line 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  CustomException
&lt;/h3&gt;

&lt;p&gt;Neste caso é criado um tipo de exceção customizado, este novo tipo é lançado, passando a exceção original como InnerException.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Desta forma o StackTrace é dividido em dois, tornando mais claro o  que aconteceu.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultado:&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;CustomException: Esta é uma exceçao customizada!
 ---&amp;gt; System.NotImplementedException: The method or operation is not implemented.
   at ClasseB.OutroMetodo() in Program.cs:line 23
   at ClasseA.UmMetodo() in Program.cs:line 12
   --- End of inner exception stack trace ---
   at ClasseA.UmMetodo() in Program.cs:line 17
   at Program.&amp;lt;Main&amp;gt;$(String[] args) in Program.cs:line 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Não existe método certo ou método errado, o importante é entender o funcionamento de cada forma de trabalho, para que o detalhamento da exceção seja apresentada da melhor forma possível. Isso fará toda a diferença no momento de identificar um bug, inclusive aquele que você não consegue reproduzir na sua máquina.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>debug</category>
      <category>csharp</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>A gambiarra de hoje pode ser o Design Pattern de amanhã!?</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Tue, 09 Nov 2021 22:37:35 +0000</pubDate>
      <link>https://forem.com/fructuoso/a-gambiarra-de-hoje-pode-ser-o-design-pattern-de-amanha-f47</link>
      <guid>https://forem.com/fructuoso/a-gambiarra-de-hoje-pode-ser-o-design-pattern-de-amanha-f47</guid>
      <description>&lt;p&gt;Escrito em 1994, por Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides. O livro "Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos" tinha como principal objetivo catalogar 23 dos padrões mais populares na época.&lt;/p&gt;

&lt;p&gt;Atualmente algumas pessoas conhecem o livro como "Gang Of Four", por conta de seus autores, sem contar que é uma referência muito mais simples de ser feita do que o próprio nome do livro.&lt;/p&gt;

&lt;p&gt;No livro, os padrões são segregados em três categorias:&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%2Fneig0qzxou9fnqegbvpe.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%2Fneig0qzxou9fnqegbvpe.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTA: O objetivo deste artigo não é falar sobre os padrões, caso você não os conheça recomendo  o site &lt;a href="https://refactoring.guru/design-patterns" rel="noopener noreferrer"&gt;refactoring.guru&lt;/a&gt;, que possui também uma versão em &lt;a href="https://refactoring.guru/pt-br/design-patterns" rel="noopener noreferrer"&gt;português&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Por definição, um padrão de projetos é uma solução vastamente utilizada para resolver um problema em comum, mas não necessariamente igual. É importante lembrar que, a implementação se torna mais simples ou mais complexa dependendo da linguagem em que ela está sendo implementada, no livro citado acima os padrões foram implementados em Smalltalk e C++.&lt;/p&gt;

&lt;p&gt;O que atualmente conhecemos como um padrão de projeto, não nasceu um "padrão". Ele se tornou um padrão com o tempo, pois seu uso se demonstrou eficiente para resolver um problema "comum". &lt;/p&gt;

&lt;p&gt;Tais implementações são criadas basicamente, para contornar uma limitação tecnológica e possivelmente se tornará obsoleta com a evolução das linguagens de programação, como por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O STRAREGY atualmente pode ser implementado usando uma arrow function.&lt;/li&gt;
&lt;li&gt;O SINGLETON pode ser completamente abstraído através dos nossos frameworks de injeção de dependências.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Outros padrões acabam evoluindo, como por exemplo o MVC, que apesar de ser um pattern, é amplamente conhecido por seus frameworks que estão presentes em praticamente todas as linguagens utilizadas atualmente.&lt;/p&gt;

&lt;p&gt;Quando você encontrar um problema onde não existe uma solução pronta na internet, lembre-se a solução pode vir a virar um padrão, afinal de contas, quem nunca pegou uma solução de um problema de um projeto e copiou para um projeto novo?&lt;/p&gt;

&lt;p&gt;Podemos dizer então dizer que...&lt;/p&gt;

&lt;p&gt;Um padrão de projetos é uma gambiarra que "viralizou"?&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Qual a sua opinião sobre isso? Manda ai nos comentários!!!&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aproveite para me seguir no &lt;a href="https://www.instagram.com/fructuoso.dev/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.youtube.com/channel/UC6GzoFA8EUgUklPyRebxOgg" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; e &lt;a href="https://www.linkedin.com/in/victorfructuoso/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>oop</category>
      <category>designpattern</category>
      <category>backend</category>
    </item>
    <item>
      <title>Otimizando os testes de uma aplicação .NET em mais de 90%</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Mon, 25 Oct 2021 16:47:59 +0000</pubDate>
      <link>https://forem.com/fructuoso/otimizando-os-testes-de-uma-aplicacao-net-em-mais-de-90-2b9d</link>
      <guid>https://forem.com/fructuoso/otimizando-os-testes-de-uma-aplicacao-net-em-mais-de-90-2b9d</guid>
      <description>&lt;p&gt;Recentemente abri uma caixa de perguntas no meu Instagram &lt;a href="https://www.instagram.com/fructuoso.dev/" rel="noopener noreferrer"&gt;@fructuoso.dev&lt;/a&gt; sobre testes de unidade e me fizeram a seguinte pergunta:&lt;/p&gt;

&lt;p&gt;Qual a diferença entre &lt;strong&gt;ClassFixture&lt;/strong&gt; e &lt;strong&gt;CollectionFixture&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Para entendermos a diferença entre os dois, primeiro precisamos ter em mente que o xUnit trabalha diferente dos demais frameworks de testes (se você quiser conhecer um pouco mais sobre esses frameworks recentemente escrevi &lt;a href="https://dev.to/fructuoso/os-3-principais-frameworks-de-testes-que-todo-desenvolvedor-net-deveria-conhecer-451h"&gt;um artigo comparando os três&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Entender o ciclo de vida dele pode impactar significante o tempo de execução dos seus testes, neste artigo veremos um cenário onde conseguimos reduzir o tempo de execução em mais de 90%.&lt;/p&gt;

&lt;p&gt;Imaginem que temos as seguintes classes de testes em nosso projeto:&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%2Fzu8yb493x1o4lyr889bx.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%2Fzu8yb493x1o4lyr889bx.png" alt="Classes de Testes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cada uma das duas classes (ClasseA e ClasseB) possuem dois cenários de testes (chamados apenas para fins de explicação de Teste1 e Teste2).&lt;/p&gt;

&lt;p&gt;Diferentemente do MSTest e do nUnit, o xUnit irá criar uma instancia da classe para executar cada um dos cenários de teste.&lt;/p&gt;

&lt;p&gt;Desta forma teremos algo 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%2Fuploads%2Farticles%2Fyw1uitiyl8p68cbzpxw1.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%2Fyw1uitiyl8p68cbzpxw1.png" alt="Cenários de Testes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sabendo disso é fácil associar que, para cada cenário de teste temos uma nova chamada ao construtor e um escopo totalmente isolado entre os cenários (que por padrão rodam em paralelo).&lt;/p&gt;

&lt;p&gt;Onde é que entram as Fixtures então?&lt;/p&gt;

&lt;p&gt;Imaginem que para um determinado conjunto de cenários de testes queremos compartilhar recursos ou estados, o compartilhamento de estado é mais comum para testes integrados pois testes de unidade devem ser totalmente isolados e independentes. Porém em testes de unidade é comum precisar reutilizar algum recurso que possua um alto custo para instanciar como por exemplo uma WebAPI ou um DbContext do EntityFramework.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;ClassFixture&lt;/strong&gt; é utilizado sempre que queremos compartilhar tais recursos com outros cenários de teste de uma mesma classe.&lt;/p&gt;

&lt;p&gt;Já o &lt;strong&gt;CollectionFixture&lt;/strong&gt; é utilizado sempre que queremos compartilhar os recursos com cenários de testes de classes distintas.&lt;/p&gt;

&lt;p&gt;Imaginem que temos o seguinte cenário:&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;FixtureX&lt;/strong&gt; é um &lt;strong&gt;ClassFixture&lt;/strong&gt;, enquanto o &lt;strong&gt;FixtureZ&lt;/strong&gt; é um &lt;strong&gt;CollectionFixture&lt;/strong&gt;, teríamos então algo 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%2Fuploads%2Farticles%2F4xniwp73ptl5aqd6nno3.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%2F4xniwp73ptl5aqd6nno3.png" alt="ClassFixture e CollectionFixture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enquanto os recursos presentes na &lt;strong&gt;FixtureX&lt;/strong&gt; são compartilhados apenas pelos cenários de teste de uma mesma classe. Os recursos presentes na &lt;strong&gt;FixtureZ&lt;/strong&gt; serão compartilhados por TODOS os cenários de testes nas classes que estiverem associadas a ela.&lt;/p&gt;

&lt;p&gt;Para recursos em que é necessário o isolamento e que apenas o próprio cenário de teste o recomendado é colocar o recurso na própria classe que implementa o cenário de teste.&lt;/p&gt;

&lt;p&gt;Ao colocar o exemplo apresentado para rodar teremos algo mais ou menos assim (o resultado pode mudar de acordo com a execução, pois lembre que os testes rodam assincronamente)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FixtureZ.Construtor
    FixtureX.Construtor
        ClasseA.Construtor
            ClasseA.Teste1
        ClasseA.Dispose
        ClasseA.Construtor
            ClasseA.Teste2
        ClasseA.Dispose
    FixtureX.Dispose
    FixtureX.Construtor
        ClasseB.Construtor
            ClasseB.Teste1
        ClasseB.Dispose
        ClasseB.Construtor
            ClasseB.Teste2
        ClasseB.Dispose
    FixtureX.Dispose
FixtureZ.Dispose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entendido o que são e como funcionam as Fixture, vamos avaliar o seguinte cenário:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temos um projeto WebAPI em que temos alguns Controllers;&lt;/li&gt;
&lt;li&gt;Precisamos testar nossa WebAPI de forma integrada usando o &lt;strong&gt;Microsoft.AspNetCore.Mvc.Testing&lt;/strong&gt; (com ajuda dele nós conseguimos levantar uma instância da nossa WebAPI em tempo de execução para que ela seja chamada via HTTP em nossos cenários de testes)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O comparativo foi feito utilizando a seguinte abordagem.&lt;/p&gt;

&lt;p&gt;Em nossa API temos um método que recebe um objeto através de uma chamada POST, passa por todas as camadas da aplicação até chegar em um banco de dados utilizando Entity Framework InMemory.&lt;/p&gt;

&lt;p&gt;A quantidade de cenários é representada pela execução do mesmo método passando entradas diferentes.&lt;/p&gt;

&lt;p&gt;Então foram explorados dois cenários, o primeiro usando uma instância compartilhada entre os cenários através do conceito de Fixture, já o segundo foi implementado com uma instância dedicada gerada através do construtor da classe.&lt;/p&gt;

&lt;p&gt;Ao simular algumas execuções chegamos aos seguintes cenários:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quantidade&lt;/th&gt;
&lt;th&gt;Instância Compartilhada&lt;/th&gt;
&lt;th&gt;Instância Dedicada&lt;/th&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;1.3&lt;/td&gt;
&lt;td&gt;-8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;2.1&lt;/td&gt;
&lt;td&gt;33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;3.3&lt;/td&gt;
&lt;td&gt;58%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;16.9&lt;/td&gt;
&lt;td&gt;92%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Como dito anteriormente as fixtures podem ser utilizadas para compartilhar recursos e estado, dependendo do cenário em que está sendo implementado pode gerar uma grande diferença de performance, porém em outros casos, o compartilhamento de recursos pode gerar efeitos colaterais no resultado dos testes, visto que os testes são executados ao mesmo tempo, logo se uma variável for modificada / consumida por mais de um teste ao mesmo tempo o resultado do teste pode variar a cada execução, ferindo assim um dos princípios básicos dos testes de unidade.&lt;/p&gt;

&lt;p&gt;Espero que vocês tenham gostado do conteúdo, não deixem de deixar um like e me seguir para que não percam nenhum conteúdo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fructuoso/DecolaDev.Catalogo" rel="noopener noreferrer"&gt;Repositório GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>performance</category>
      <category>csharp</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Os 3 principais frameworks de testes que todo desenvolvedor .NET deveria conhecer  </title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Tue, 19 Oct 2021 02:15:21 +0000</pubDate>
      <link>https://forem.com/fructuoso/os-3-principais-frameworks-de-testes-que-todo-desenvolvedor-net-deveria-conhecer-451h</link>
      <guid>https://forem.com/fructuoso/os-3-principais-frameworks-de-testes-que-todo-desenvolvedor-net-deveria-conhecer-451h</guid>
      <description>&lt;p&gt;Todo bom desenvolvedor sabe a importância de testar seu código, o uso de testes automatizados nos permite acelerar esse processo onde conseguimos testar centenas, talvez milhares de cenários de testes distintos em questão de segundos.&lt;/p&gt;

&lt;p&gt;Quando o assunto é .NET temos três grandes players brigando pela preferência dos desenvolvedores.&lt;/p&gt;

&lt;h2&gt;
  
  
  nUnit
&lt;/h2&gt;

&lt;p&gt;nUnit é um framework de teste de unidade que foi baseado no JUnit, sua versão 3 (mais atual), foi completamente reescrita com diversas novas funcionalidades de suporte para diversas linguagens da plataforma .NET.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
    &lt;td&gt;Versão Atual&lt;/td&gt;
    &lt;td&gt;3.13.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Downloads&lt;/td&gt;
    &lt;td&gt;140.2M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Site&lt;/td&gt;
    &lt;td&gt;&lt;a href="https://nunit.org/"&gt;https://nunit.org/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  MSTest
&lt;/h2&gt;

&lt;p&gt;MSTest é o mais antigo da nossa lista, ele já foi o framework de teste padrão do Visual Studio (que atualmente conta com template de projeto de teste para todos os três frameworks da nossa lista)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
    &lt;td&gt;Versão Atual&lt;/td&gt;
    &lt;td&gt;16.11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Downloads&lt;/td&gt;
    &lt;td&gt;252.3M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Site&lt;/td&gt;
    &lt;td&gt;&lt;a href="https://github.com/microsoft/testfx"&gt;https://github.com/microsoft/testfx&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  xUnit
&lt;/h2&gt;

&lt;p&gt;O xUnit é o framework mais recente desta lista, foi desenvolvido pelo criador do nUnit v2 com o objetivo de simplificar e modernizar a forma como escrevemos testes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
    &lt;td&gt;Versão Atual&lt;/td&gt;
    &lt;td&gt;2.4.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Downloads&lt;/td&gt;
    &lt;td&gt;166.4M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;Site&lt;/td&gt;
    &lt;td&gt;&lt;a href="https://github.com/xunit/xunit"&gt;https://github.com/xunit/xunit&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Notem que apesar de mais novo o xUnit já supera o volume de downloads do nUnit&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Principais Recursos
&lt;/h2&gt;

&lt;p&gt;Abaixo uma relação com os principais recursos que os frameworks possuem:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;[Test]&lt;/th&gt;
&lt;th&gt;[TestMethod]&lt;/th&gt;
&lt;th&gt;[Fact]&lt;/th&gt;
&lt;th&gt;Define que o método representa   um cenário de teste&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;[TestFixture]&lt;/td&gt;
&lt;td&gt;[TestClass]&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Marca uma determinada classe   como sendo uma classe de testes. &lt;br&gt; No xUnit essa identificação   funciona a partir do método, todos os métodos marcados como testes através do   atributo (Fact ou Theory) das classes publicas presentes no assembly são testados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assert.That&lt;br&gt;Record.Exception&lt;/td&gt;
&lt;td&gt;[ExpectedException]&lt;/td&gt;
&lt;td&gt;Assert.Throws&lt;br&gt;Record.Exception&lt;/td&gt;
&lt;td&gt;Enquanto o MSTest define a   Exceção esperada através do atributo ExpectedException o nUnit e o xUnit   trabalham de forma semelhante permitindo que um o código seja processado e   exceção seja retornada em uma váriável permitindo testar não apenas o tipo da   exceção, mas também suas propriedades.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[SetUp]&lt;/td&gt;
&lt;td&gt;[TestInitialize]&lt;/td&gt;
&lt;td&gt;Constructor&lt;/td&gt;
&lt;td&gt;Método responsável por fazer o   &lt;strong&gt;SetUp&lt;/strong&gt; do cenário de teste.&lt;br&gt;É válido lembrar que este método é   executado antes de cada teste.&lt;br&gt;Tanto o nUnit quanto o MSTest   trabalham com atributos para identificar o método em questão, já o xUnit usa   o construtor da classe para realizar este papel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[TearDown]&lt;/td&gt;
&lt;td&gt;[TestCleanup]&lt;/td&gt;
&lt;td&gt;IDisposable.Dispose&lt;/td&gt;
&lt;td&gt;Método responsável por fazer o   &lt;strong&gt;TearDown&lt;/strong&gt; do cenário de teste.&lt;br&gt;É válido lembrar que este método é   executado ao final de cada teste.&lt;br&gt;Tanto o nUnit quanto o MSTest   trabalham com atributos para identificar o método em questão, já o xUnit usa   o &lt;em&gt;Dispose&lt;/em&gt; da classe para realizar este papel, para que funcione é preciso   implementar a interface &lt;em&gt;IDisposable&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[OneTimeSetUp]&lt;/td&gt;
&lt;td&gt;[ClassInitialize]&lt;/td&gt;
&lt;td&gt;IClassFixture&lt;/td&gt;
&lt;td&gt;Método responsável por fazer o   &lt;strong&gt;SetUp&lt;/strong&gt; da classe, ou seja este código é executado uma única vez para todos   os testes contidos dento da classe em questão.&lt;br&gt;Tanto o nUnit quanto   o MSTest trabalham com atributos para identificar o método em questão, já o   xUnit usa a interface &lt;em&gt;IClassFixture&lt;/em&gt;, basta que a classe em questão   implemente essa inteface (que não possui nenhum método) ela funciona apenas   como marcação para que a Fixture implementada seja devidamente instanciada e   passada para o construtor da classe.&lt;br&gt;É valido lembrar que apenas uma   instancia da Fixture será criada para aquela classe e TODOS os métodos   presentes nela compartilharão a mesma instância.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[OneTimeTearDown]&lt;/td&gt;
&lt;td&gt;[ClassCleanup]&lt;/td&gt;
&lt;td&gt;IClassFixture&lt;/td&gt;
&lt;td&gt;Método responsável por fazer o   &lt;strong&gt;TearDown&lt;/strong&gt; da classe, ou seja este código é executado uma única vez para   todos os testes contidos dento da classe em questão.&lt;br&gt;Tanto o nUnit   quanto o MSTest trabalham com atributos para identificar o método em questão,   já o xUnit usa a interface &lt;em&gt;IClassFixture&lt;/em&gt;, neste caso a Fixture em questão   implemente o método &lt;em&gt;Dispose&lt;/em&gt; da interface &lt;em&gt;IDisposable&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[Ignore("reason")]&lt;/td&gt;
&lt;td&gt;[Ignore]&lt;/td&gt;
&lt;td&gt;[Fact(Skip="reason")]&lt;/td&gt;
&lt;td&gt;Utilizado para determinar que um   determinado cenário de teste deve ser ignorado temporariamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[Property]&lt;/td&gt;
&lt;td&gt;[TestProperty]&lt;/td&gt;
&lt;td&gt;[Trait]&lt;/td&gt;
&lt;td&gt;Atributo utilizado para atribuir   metadados aos cenários de testes que podem auxiliar no processo de   organização dos mesmos (possiveis relatórios com resultados da execução dos   testes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[Theory]&lt;/td&gt;
&lt;td&gt;[DataSource]&lt;/td&gt;
&lt;td&gt;[Theory]&lt;/td&gt;
&lt;td&gt;Utilizado para atribuir mais de   uma entrada para um mesmo cenário de testes, por exemplo: Imaginem que   precisamos testar um método responsável por validar uma formula matemática,   porém nós queremos testar diversas entradas (inputs) com o uso desse recurso   conseguimos realizar essa validação sem a necessidade de usar uma estrutura   de loop (for / while).&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Assertions (Verificações)
&lt;/h2&gt;

&lt;p&gt;Principais formas de verificar se um cenário de teste está de acordo com o esperado.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;nUnit&lt;/th&gt;
&lt;th&gt;MSTest&lt;/th&gt;
&lt;th&gt;xUnit&lt;/th&gt;
&lt;th&gt;Comentários&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Is.EqualTo&lt;/td&gt;
&lt;td&gt;AreEqual&lt;/td&gt;
&lt;td&gt;Equal&lt;/td&gt;
&lt;td&gt;Verifica se dois objetos são   iguais (EqualTo)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.EqualTo&lt;/td&gt;
&lt;td&gt;AreNotEqual&lt;/td&gt;
&lt;td&gt;NotEqual&lt;/td&gt;
&lt;td&gt;Verifica dois objetos são   diferentes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.SameAs&lt;/td&gt;
&lt;td&gt;AreNotSame&lt;/td&gt;
&lt;td&gt;NotSame&lt;/td&gt;
&lt;td&gt;Verifica dois objetos são   instancias diferentes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.SameAs&lt;/td&gt;
&lt;td&gt;AreSame&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;td&gt;Verifica se dois objetos são   mesma instância.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does.Contain&lt;/td&gt;
&lt;td&gt;Contains&lt;/td&gt;
&lt;td&gt;Contains&lt;/td&gt;
&lt;td&gt;Verifica se um objeto está   contido em uma colecão, se aplica também para strings (sub-string).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does.Not.Contain&lt;/td&gt;
&lt;td&gt;DoesNotContain&lt;/td&gt;
&lt;td&gt;DoesNotContain&lt;/td&gt;
&lt;td&gt;Verifica se um objeto NÃO está contido em   uma colecão, se aplica também para strings (sub-string).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throws.Nothing&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit é utilizado   juntamente com o &lt;strong&gt;Assert.That&lt;/strong&gt; para garantir que uma determinada exceção   não foi levantada.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no MSTest serve para fazer   um teste falhar arbitrariamente utilizado em cenários em que a regra de   validação é aplicada utilizando "IFs"&lt;br&gt;Para o nUnit e xUnit   a alternativa é trabalhar com Is.True(nUnit) e True(xUnit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.GreaterThan&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit serve para validar   se o resultado é maior que um determinado valor.&lt;br&gt;Para o MSTest e   xUnit a alternativa é trabalhar com IsTrue (MSTest) e True (xUnit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.InRange&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;InRange&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit e no xUnit serve   para validar se um objeto está dentro de um intervalo pré-definido, funciona   para qualquer tipo que implementa a interface &lt;em&gt;IComparable&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.AssignableFrom&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;IsAssignableFrom&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit e no   xUnit serve para validar se um objeto é de um tipo pré-definido (ou derivado)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Empty&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Empty&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit e no   xUnit serve para validar se uma coleção está vazia.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.False&lt;/td&gt;
&lt;td&gt;IsFalse&lt;/td&gt;
&lt;td&gt;False&lt;/td&gt;
&lt;td&gt;Verifica se uma determinada operação retorna   &lt;em&gt;false&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.InstanceOf&lt;/td&gt;
&lt;td&gt;IsInstanceOfType&lt;/td&gt;
&lt;td&gt;IsType&lt;/td&gt;
&lt;td&gt;Diferentemente do AssignableFrom   o InstanceOf verifica se um objeto é um determinado tipo, mas neste caso não   considera derivados.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.NaN&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit é   utilizado em conjunto com o Assert.That para determinar se um objeto é um   número.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.AssignableFrom&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit   representa o cenário oposto do AssignableFrom verificando se um objeto não é   de um determinado tipo ou derivado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.Empty&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;NotEmpty&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit e xUnit   verifica se uma coleção possui pelo menos um elemento.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.InstanceOf&lt;/td&gt;
&lt;td&gt;IsNotInstanceOfType&lt;/td&gt;
&lt;td&gt;IsNotType&lt;/td&gt;
&lt;td&gt;Representa o cenário oposto do   InstanceOf verifica se um objeto não é de um tipo e não considera seus   derivados.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.Null&lt;/td&gt;
&lt;td&gt;IsNotNull&lt;/td&gt;
&lt;td&gt;NotNull&lt;/td&gt;
&lt;td&gt;Verifica se um objeto é diferente de null.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Null&lt;/td&gt;
&lt;td&gt;IsNull&lt;/td&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Verifica se um objeto é null.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.True&lt;/td&gt;
&lt;td&gt;IsTrue&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;td&gt;Verifica se uma operação retorna &lt;em&gt;true&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.LessThan&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit serve para validar   se um objeto é menor que um determinado valor.&lt;br&gt;Funciona para   qualquer tipo de objeto que implementa a interface   &lt;em&gt;IComparable&lt;/em&gt;&lt;br&gt;Para o MSTest e xUnit a alternativa é trabalhar com   IsTrue (MSTest) e True (xUnit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is.Not.InRange&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;NotInRange&lt;/td&gt;
&lt;td&gt;Presente apenas no nUnit e no   xUnit serve para validar se um objeto está fora de um intervalo pré-definido,   funciona para qualquer tipo de objeto que implementa a interface   &lt;em&gt;IComparable&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throws.TypeOf&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Throws&lt;/td&gt;
&lt;td&gt;Verifica se uma determinada   operação lança uma exceção pré-definida.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Se você curtiu o post, deixe o seu coração e compartilhe com seus amigos.&lt;/p&gt;

&lt;p&gt;Aproveite para me seguir aqui, no YouTube e no Instagram. Os links estão na BIO.&lt;/p&gt;

&lt;p&gt;Em breve lançarei uma série de vídeos demonstrando uma mesma aplicação sendo testado pelos três frameworks. Fiquem ligados para não perder nenhum detalhe.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>nunit</category>
      <category>mstest</category>
      <category>xunit</category>
    </item>
    <item>
      <title>Qual a diferença entre um MOCK e um STUB?</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Thu, 14 Oct 2021 01:02:46 +0000</pubDate>
      <link>https://forem.com/fructuoso/qual-a-diferenca-entre-um-mock-e-um-stub-ob3</link>
      <guid>https://forem.com/fructuoso/qual-a-diferenca-entre-um-mock-e-um-stub-ob3</guid>
      <description>&lt;p&gt;Recentemente me mandaram a seguinte pergunta: "Qual a diferença entre stub e mock?"&lt;/p&gt;

&lt;p&gt;Quando falamos sobre as estratégias utilizadas para testar um código possuímos os seguintes conceitos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fake
&lt;/h2&gt;

&lt;p&gt;O Fake representa uma implementação real mas não necessariamente igual a que será utilizada em ambiente produtivo, como por exemplo um repositório persistido em memória; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Obs.: O Fake é uma técnica utilizada em casos de testes integrados, onde nós testamos mais de uma camada em um único cenário de testes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vejam o exemplo abaixo:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Estamos criando uma classe concreta chamada ProdutoRepositoryFake que efetivamente implementa a interface IProdutoRepository, porém de uma forma simplificada, e potencialmente diferente da que será publicada em produção.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spy
&lt;/h2&gt;

&lt;p&gt;Spies são utilizados em casos onde queremos validar o comportamento de um método e sua interação com suas dependências, neste caso as dependências não são modificadas;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Obs.: O Spy é uma técnica utilizada em casos de testes Integrados, onde nós testamos mais de uma camada em um único cenário de testes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vejam o exemplo abaixo:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Estamos aplicando um Spy no nosso ProdutoRepositoryFake (pois nesse código de exemplo é a unica classe concreta que deriva de IProdutoRepository que nós temos), este mesmo exemplo poderia ser aplicado com qualquer classe concreta.&lt;/p&gt;

&lt;p&gt;Neste exemplo foi preciso usar a interface IProdutoRepository e a classe ProdutoRepositoryFake como base para isso (linha 4).&lt;/p&gt;

&lt;p&gt;Por que o código da linha 3 não funciona? Não funciona porque os métodos em questão não possuem o modificador "virtual", ou seja, ele não pode ser sobrescrito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stub
&lt;/h2&gt;

&lt;p&gt;Stub é uma implementação que nos permite fornecer respostas prontas, são utilizados para cenários onde queremos validar apenas o resultado;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vejam o exemplo abaixo:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Estamos criando um stub de um IProdutoRepository onde sempre que o método Obter for chamado passando o parâmetro id igual a 1, ele deve retornar um Produto { Id = 1, Nome = "TECLADO" }&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Obs.: Está sendo utilizado um framework para simplificar a implementação do Stub, em um cenário natural, seria necessário criar um ProdutoRepositoryStub que imlpementasse a interface IProdutoRepository, o que seria muito mais verboso.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mock
&lt;/h2&gt;

&lt;p&gt;Diferentemente do Stub, o mock possui a capacidade de validar o comportamento da implementação, validando por exemplo quantas vezes um determinado método foi chamado, quais foram os parâmetros passados dentre outras informações, ou seja, o mock possui a capacidade do Spy e do Stub juntas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vejam o exemplo abaixo:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Estamos criando uma instancia do IProdutoRepository utilizando um Mock, sendo assim nós conseguimos definir arbitrariamente o retorno para os métodos que esta interface possui.&lt;/p&gt;

&lt;p&gt;Além disso nós conseguimos também validar posteriormente se um determinado método foi chamado, com quais parametros foi chamado e quantas vezes ele foi chamado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dummy
&lt;/h2&gt;

&lt;p&gt;Um objeto dummy é um objeto que nós utilizamos apenas para viabilizar a execução do nosso código, mas que para o nosso teste ele não será utilizado em momento algum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vejam o exemplo abaixo:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Estamos criando um método auxiliar que produz um Produto válido. Para o escopo do nosso teste é irrelevante conhecer as características de um produto válido, os valores atribuídos nas propriedades deste objeto também são irrelevantes.&lt;/p&gt;

&lt;p&gt;Imagine um cenário onde temos dezenas de testes que precisam receber um Produto válido, eis que uma nova regra de validação é criada.&lt;/p&gt;

&lt;p&gt;Automaticamente TODOS os testes que dependem de um Produto válido começarão a falhar (o que é bom), se não fosse pelo Dummy seria necessário modificar todos os testes um a um.&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerações Finais
&lt;/h3&gt;

&lt;p&gt;Segue o repositório no GitHub com os exemplos utilizados &lt;a href="https://github.com/fructuoso/Doubles.Types"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É válido lembrar que para estes exemplos estou usando o Moq que reduz significantemente a complexidade de escrever um duble de código.&lt;/p&gt;

&lt;p&gt;Agora, mesmo que você prefira continuar falando que vai mocar tudo, você entende e sabe a diferença de cada uma dessas técnicas.&lt;/p&gt;

&lt;p&gt;Se você gostou aproveite para deixar o seu Like e me seguir aqui e nas outras redes &lt;a href="https://linktr.ee/fructuosodev"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://martinfowler.com/articles/mocksArentStubs.html"&gt;Mocks Aren't Stubs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>tests</category>
      <category>unittests</category>
      <category>xunit</category>
    </item>
    <item>
      <title>7 passos para construir uma P.o.C. LIKE A BOSS</title>
      <dc:creator>Víctor Fructuoso</dc:creator>
      <pubDate>Sun, 03 Oct 2021 13:09:14 +0000</pubDate>
      <link>https://forem.com/fructuoso/7-passos-para-construir-uma-p-o-c-like-a-boss-23lm</link>
      <guid>https://forem.com/fructuoso/7-passos-para-construir-uma-p-o-c-like-a-boss-23lm</guid>
      <description>&lt;h2&gt;
  
  
  7 passos para construir uma P.o.C. LIKE A BOSS
&lt;/h2&gt;

&lt;p&gt;Todos nós já nos deparamos com situações em que precisamos desenvolver algo novo, ou que possui requisitos peculiares e não temos uma solução "pronta".&lt;/p&gt;

&lt;p&gt;Em alguns casos desenvolver, ou tentar desenvolver, a solução completa pode demandar tempo e/ou dinheiro (normalmente uma coisa leva a outra).&lt;/p&gt;

&lt;p&gt;Uma das alternativas para evitar um grande investimento quando não há um nível aceitável de segurança no caminho que está sendo seguido, é realizar pequenos experimentos. Afinal de contas se algo der errado, o prejuízo será muito menor e haverá tempo para pensar em outras alternativas.&lt;/p&gt;

&lt;p&gt;No desenvolvimento de software esses experimentos são chamados de POC (Proof Of Concept), ou "Prova de Conceito".&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Requisitos
&lt;/h3&gt;

&lt;p&gt;A primeira etapa do processo é entender quais são nossos requisitos e restrições, pois todo o trabalho será realizado com objetivo de validar o quão aderente a eles o experimento é.&lt;/p&gt;

&lt;p&gt;Nesta etapa vamos também dividir nossos requisitos em essenciais e desejáveis. Esta segregação ajudará em todo o processo. Pensem comigo:&lt;/p&gt;

&lt;p&gt;Faz sentido continuar investindo tempo e dinheiro em um estudo em que nós já sabemos que não atenderá nossos requisitos essenciais?&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Estabeleça Critérios (métricas)
&lt;/h3&gt;

&lt;p&gt;Uma vez que os requisitos da prova de conceito estão claros é necessário estabelecer quais os critérios que serão utilizados para evidenciar se a solução desenvolvida atende ou não aos requisitos estabelecidos inicialmente, esses critérios devem ser tangíveis, ou seja, nossas respostas para estes critérios não podem ser subjetivas.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Delimite o Escopo
&lt;/h3&gt;

&lt;p&gt;Nesta etapa será definido o que efetivamente será implementado na prova de conceito, lembrando sempre que o principal objetivo da prova de conceito é poupar tempo e dinheiro, logo, o esforço para a construção da mesma deve ser significantemente menor que o esforço para construir a solução definitiva.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Plano de Ação
&lt;/h3&gt;

&lt;p&gt;Com o escopo estabelecido é preciso elaborar um plano de ação indicando como o escopo será atendido e quanto tempo será investido para validar a teoria, ou seja, precisamos identificar as etapas que precisam ser realizadas e o esforço estimado para a conclusão de cada uma delas.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Hands-On (Implementação)
&lt;/h3&gt;

&lt;p&gt;Durante a implementação efetiva da POC precisamos ter em mente que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Este código deve ser funcional, porém ele é apenas um experimento;&lt;/li&gt;
&lt;li&gt;Apesar de não possuir as mesmas restrições de qualidade que um código "normal", o código precisa estar legível para que possa ser analisado e potencialmente reutilizado em uma implementação definitiva;&lt;/li&gt;
&lt;li&gt;Seus esforços devem SEMPRE estar 100% direcionados para responder às perguntas estabelecidas anteriormente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Documente
&lt;/h3&gt;

&lt;p&gt;Com a prova de conceito devidamente implementada é hora de voltar às métricas e validar o quanto a solução construída é aderente aos requisitos e restrições definidos no primeiro passo.&lt;/p&gt;

&lt;p&gt;Nesse momento os requisitos que já estavam divididos em (essenciais e desejáveis) agora passam a ser sub-divididos também em (simples e complexos) para implementar de forma definitiva.&lt;/p&gt;

&lt;p&gt;É recomendável documentar os resultados encontrados para apresentar aos stakeholders e manter o histórico do porque tal decisão foi tomada.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;NOTA: Pode ser necessário testar outras abordagens e comparar os resultados até que se chegue em um resultado satisfatório.&lt;/u&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Road Map
&lt;/h3&gt;

&lt;p&gt;Ao chegar nessa etapa temos nossa prova de conceito efetivamente pronta para ser desenvolvida para se tornar um entregável.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>productivity</category>
      <category>development</category>
      <category>agile</category>
    </item>
  </channel>
</rss>
