<?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: Steven Victor</title>
    <description>The latest articles on DEV Community by Steven Victor (@stevensunflash).</description>
    <link>https://dev.to/stevensunflash</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%2F113340%2Ff1d42f94-fbeb-46d8-858d-20ec87a5ae65.jpg</url>
      <title>DEV Community: Steven Victor</title>
      <link>https://dev.to/stevensunflash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stevensunflash"/>
    <language>en</language>
    <item>
      <title>Using GraphQL in Golang</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Tue, 01 Sep 2020 16:50:43 +0000</pubDate>
      <link>https://dev.to/stevensunflash/using-graphql-in-golang-3gg0</link>
      <guid>https://dev.to/stevensunflash/using-graphql-in-golang-3gg0</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From the official GraphQL documentation, GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need, and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.&lt;/p&gt;

&lt;p&gt;I will be demonstrating with a simple application of how you start using GraphQL with Golang using the awesome &lt;a href="https://github.com/99designs/gqlgen"&gt;gqlgen&lt;/a&gt; package&lt;/p&gt;

&lt;p&gt;There are other packages used in Golang for GraphQL implementations, but these are the few reasons we use &lt;strong&gt;gqlgen&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gqlgen is based on a Schema first approach — You get to Define your API using the GraphQL Schema Definition Language.&lt;/li&gt;
&lt;li&gt;gqlgen prioritizes Type safety — You should never see map[string]interface{} here.&lt;/li&gt;
&lt;li&gt;gqlgen enables Codegen — We generate the boring bits, so you can focus on building your app quickly. You can get a complete read &lt;a href="https://gqlgen.com"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The purpose of this article is to give you a hands-on introduction to using Graphql in Golang. As such, we won't focus on definitions of terms in great detail.&lt;/p&gt;

&lt;p&gt;We will be building a &lt;a href="https://github.com/victorsteven/multi-choice-graphql-go-app"&gt;multi-choice question and answer&lt;/a&gt; application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Basic Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can get the complete code for this article &lt;a href="https://github.com/victorsteven/multi-choice-graphql-go-app"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a folder of the project at any location on your computer(preferably where you have your Go projects), initialize go mod, then install the package gqlgen package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir multi-choice
cd multi-choice
go mod init multi-choice
go get github.com/99designs/gqlgen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then create a &lt;strong&gt;Makefile&lt;/strong&gt; to house all the commands that will be used.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Makefile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Content:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;init&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go run github.com/99designs/gqlgen init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Initialize using:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After running the above command, the project structure will look like this(from the &lt;a href="https://gqlgen.com/getting-started"&gt;documentation&lt;/a&gt;):&lt;/p&gt;

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

&lt;p&gt;The end product of the application we will be building has this structure:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JXnrdEZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/51o86t7z4ol7tjvwj0uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JXnrdEZ9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/51o86t7z4ol7tjvwj0uy.png" alt="Alt Text" width="880" height="1361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will now customize to fit our use case.&lt;br&gt;
The &lt;strong&gt;gqlgen.yml&lt;/strong&gt; is modified to be:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Schemas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A GraphQL schema is at the core of any GraphQL server implementation. It describes the functionality available to the client applications that connect to it. - &lt;a href="https://www.tutorialspoint.com/graphql/graphql_schema.htm#:~:text=A%20GraphQL%20schema%20is%20at,build%20an%20interface%20around%20it.&amp;amp;text=Client%20applications%20can%20query%20the%20schema%20within%20its%20capabilities."&gt;Tutorialspoint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;gqlgen ships with a default schema.graphql. We can create more schemas based on project requirements.&lt;/p&gt;

&lt;p&gt;The look of the schemas directory:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---0z8nAiB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6lhwfwy8hfjc2zx0lj3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---0z8nAiB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6lhwfwy8hfjc2zx0lj3l.png" alt="Alt Text" width="880" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I thought it neat to have the schema for a particular functionality to be in just one file(including the &lt;strong&gt;mutation&lt;/strong&gt; and the &lt;strong&gt;query&lt;/strong&gt;).&lt;br&gt;
Rather than have a huge mutation/query that houses all mutation/query descriptions, we will have several, based on the number of concerns/features we are to implement.&lt;/p&gt;

&lt;p&gt;In a nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;#schema here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;#schema here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Extended:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;extend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;#schema here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 

&lt;/span&gt;&lt;span class="k"&gt;extend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;#schema here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Question Schema:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The Question Option Schema:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Observe there is no mutation/query. Well, question options are created only when questions are created, so they are not created independently.&lt;br&gt;
The QuestionOptionInput was used as an argument in the Question schema defined above.

&lt;p&gt;The Answer Schema:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Note:&lt;/p&gt;

&lt;p&gt;Graphql does not permit more one definition of mutation/query. So we had to use the &lt;strong&gt;extend&lt;/strong&gt; keyword when defining other mutation/query for other functionalities.&lt;br&gt;
I don't consider it neat to have all mutation/query in one file as I have often seen from projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can always add custom types outside the built-in types(ID, String, Boolean, Float, Int) to do so, we use the &lt;strong&gt;scalar&lt;/strong&gt; keyword. &lt;br&gt;
A good example is Time(created_at, updated_at, etc)&lt;br&gt;
That can be defined in the &lt;strong&gt;schema.graphql&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We don't need to bother adding the marshaling behavior to Go types; gqlgen has taken care of that. This also applies to other custom scalar types such as &lt;em&gt;Any&lt;/em&gt;, &lt;em&gt;Upload&lt;/em&gt;, and &lt;em&gt;Map&lt;/em&gt;. Read more &lt;a href="https://gqlgen.com/reference/scalars"&gt;here&lt;/a&gt;. To add your own custom type, you will need to wire up the marshaling behavior to Go types.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Models' directory structure:&lt;/p&gt;

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

&lt;p&gt;The graphql schema defined in the &lt;strong&gt;schemas&lt;/strong&gt; directory is translated into Go code and saved in the &lt;strong&gt;models.go&lt;/strong&gt; file.&lt;br&gt;&lt;br&gt;
For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Question&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;questionOption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;QuestionOption&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Is translated to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Question&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;             &lt;span class="kt"&gt;string&lt;/span&gt;            &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;Title&lt;/span&gt;          &lt;span class="kt"&gt;string&lt;/span&gt;            &lt;span class="s"&gt;`json:"title"`&lt;/span&gt;
    &lt;span class="n"&gt;QuestionOption&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;QuestionOption&lt;/span&gt; &lt;span class="s"&gt;`json:"questionOption"`&lt;/span&gt;
    &lt;span class="n"&gt;CreatedAt&lt;/span&gt;      &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;         &lt;span class="s"&gt;`json:"createdAt"`&lt;/span&gt;
    &lt;span class="n"&gt;UpdatedAt&lt;/span&gt;      &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;         &lt;span class="s"&gt;`json:"updatedAt"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Where &lt;strong&gt;QuestionOption&lt;/strong&gt; is a type just like &lt;strong&gt;Question&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For us to translate schema to an actual Go code, we need to run a generate command.&lt;br&gt;
Update the &lt;strong&gt;Makefile&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;init&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go run github.com/99designs/gqlgen init

&lt;span class="nl"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go run github.com/99designs/gqlgen

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

&lt;/div&gt;


&lt;p&gt;Then run the generate command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;make&lt;/span&gt; &lt;span class="err"&gt;generate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will generate the following in the models.go file&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Observe that the &lt;strong&gt;mutation&lt;/strong&gt; and &lt;strong&gt;query&lt;/strong&gt; translations are not here. That will be in the &lt;strong&gt;resolvers&lt;/strong&gt; as we will see later.&lt;/p&gt;

&lt;p&gt;To have a different model for each schema, you can inform the gqlgen.yml about them. Read more &lt;a href="https://gqlgen.com/reference/resolvers"&gt;here&lt;/a&gt; I think is neat to have the models inside the models.go file for now.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom hooks
&lt;/h4&gt;

&lt;p&gt;You can define hooks to alter your model's behavior. In my case, I want the &lt;strong&gt;id&lt;/strong&gt; to be a randomly generated string(UUID). So, to do that, I have to use &lt;a href="https://gorm.io/docs/hooks.html"&gt;gorm's&lt;/a&gt; &lt;strong&gt;BeforeCreate&lt;/strong&gt; hook:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Custom tags
&lt;/h4&gt;

&lt;p&gt;We might need to add extra tags to our model structs. For instance, we might add a "db" tag, a "gorm" tag, a "bson" tag(when using MongoDB).&lt;/p&gt;

&lt;p&gt;This is defined in the path: &lt;strong&gt;models/model_tags&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can update the generate command in the &lt;strong&gt;Makefile&lt;/strong&gt; so that we always add the model tags each time we run the generate command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    go run github.com/99designs/gqlgen &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go run ./app/models/model_tags/model_tags.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running the generate command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will now have the &lt;strong&gt;models.go&lt;/strong&gt; updated as:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Resolvers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Structure:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lzEO-_ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tghnxv1z7zoy6xu8l2lh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lzEO-_ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tghnxv1z7zoy6xu8l2lh.png" alt="Alt Text" width="880" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A resolver acts as a GraphQL query handler&lt;br&gt;
Mutations and Queries are translated into Go code and placed in the resolvers when the generate command is run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, for a mutation like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;CreateQuestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;QuestionInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;QuestionResponse&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;


&lt;p&gt;The corresponding translation is:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mutationResolver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CreateQuestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuestionInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuestionResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"not implemented"&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;ul&gt;
&lt;li&gt;The article &lt;em&gt;slightly&lt;/em&gt; adheres to DDD(Domain Driven Design) principles. So I thought it cool to have the &lt;strong&gt;resolver.go&lt;/strong&gt; and all resolver related files to be placed in the &lt;em&gt;interfaces&lt;/em&gt; directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Question Resolver:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The Answer Resolver:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The above are simple crud operations. We use dependency injection to require external functionalities. The dependencies used are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QuestionService&lt;/li&gt;
&lt;li&gt;QuestionOptionService&lt;/li&gt;
&lt;li&gt;AnsService&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which are defined in the base resolver file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This makes our resolver methods to be easily testable. We can easily replace those dependencies with fake ones, so we can achieve unit testing. Kindly check the test files.&lt;/p&gt;

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

&lt;p&gt;We injected some dependencies into our resolver above. Let's define those. This will be done in the domain:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JE00VfjN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80n5qfux4a2dvz1mhr12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JE00VfjN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/80n5qfux4a2dvz1mhr12.png" alt="Alt Text" width="880" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Question Repository:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The Question Option Repository:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The Answer Repository:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Infrastructure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will now implement the interfaces defined above in the infrastructure layer:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m3Qxpj57--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s46wkv4ioxqnutnixaot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m3Qxpj57--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s46wkv4ioxqnutnixaot.png" alt="Alt Text" width="880" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implementing Question Methods:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Implementing Question Option Methods:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Implementing Answer Methods:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;From the above implementations, &lt;strong&gt;gorm&lt;/strong&gt; is used as the ORM to interacting with the PostgreSQL database.&lt;/p&gt;

&lt;p&gt;Next, let's look at db.go file, which has functions that open the db and run migration.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Running the Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have pretty much everything wired. &lt;br&gt;
Let's now connect to the database, pass down the db instance.&lt;br&gt;
All environmental variables are stored in a &lt;strong&gt;.env&lt;/strong&gt; file at the root directory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the root directory, create the &lt;strong&gt;main.go&lt;/strong&gt; file. The content of the &lt;strong&gt;server.go&lt;/strong&gt; that graphql initial setup ships with are added to the main.go file, and the file is deleted.&lt;/p&gt;


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


&lt;p&gt;We can update the &lt;strong&gt;Makefile&lt;/strong&gt; that have the run and the test commands:&lt;/p&gt;


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


&lt;p&gt;Run the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h4&gt;
  
  
  &lt;strong&gt;Trying Some Endpoints&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Question with multi-choice&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Get one question with multi-choice&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Answer the question:&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;Running the tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Integration Tests&lt;br&gt;
You will need to create a test database and update the &lt;strong&gt;.env&lt;/strong&gt; file with the credentials to run the integration tests in the infrastructure layer. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit Tests&lt;br&gt;
The dependencies from the infrastructure layer are swapped with fake implementation. This allowed us to unit test the resolvers in the interfaces layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having updated the &lt;strong&gt;.env&lt;/strong&gt;, run all test cases from the root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;You have seen how simple it can be to start using graphql in golang. I hope you enjoyed the article. &lt;br&gt;
Get the complete code for this article &lt;a href="https://github.com/victorsteven/multi-choice-graphql-go-app"&gt;here&lt;/a&gt;&lt;br&gt;
I will be expanding on the current idea in future articles to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File upload &lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

&lt;p&gt;You can follow me on &lt;a href="https://twitter.com/stevensunflash"&gt;twitter&lt;/a&gt; for any future announcement.&lt;/p&gt;

&lt;p&gt;Thank you.&lt;/p&gt;

</description>
      <category>go</category>
      <category>graphql</category>
      <category>testing</category>
    </item>
    <item>
      <title>Converting your Unit and End-To-End Test Suites from Mocha, Chai, and Sinon to Jest in Nodejs.</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Sun, 22 Mar 2020 21:44:59 +0000</pubDate>
      <link>https://dev.to/stevensunflash/converting-your-unit-and-end-to-end-test-suites-from-mocha-chai-and-sinon-to-jest-in-nodejs-b6c</link>
      <guid>https://dev.to/stevensunflash/converting-your-unit-and-end-to-end-test-suites-from-mocha-chai-and-sinon-to-jest-in-nodejs-b6c</guid>
      <description>&lt;p&gt;I started on a project recently and Jest is a requirement for testing. Making the switch from what I am already used to(mocha, chai, and sinon) is not difficult though, I wish to explain in this article some of the differences I observed using code samples. &lt;/p&gt;

&lt;h3&gt;
  
  
  Mocha
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mochajs.org"&gt;Mocha&lt;/a&gt; is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting while mapping uncaught exceptions to the correct test cases. In other words, mocha is a javascript test framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.chaijs.com"&gt;Chai&lt;/a&gt; is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sinon
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://sinonjs.org"&gt;Sinon&lt;/a&gt; provides standalone test spies, stubs and mocks for JavaScript. &lt;/p&gt;

&lt;h3&gt;
  
  
  Jest
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://jestjs.io"&gt;Jest&lt;/a&gt; is a delightful JavaScript Testing Framework with a focus on simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Mocha or Jest?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Both Mocha and Jest are both javascript test frameworks(test runners).&lt;br&gt;
A vivid comparison between both mocha and jest is found &lt;a href="https://blog.usejournal.com/jest-vs-mocha-whats-the-difference-235df75ffdf3"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jest comes with built-in mocking and assertion abilities. In addition, Jest runs your tests concurrently in parallel, providing a smoother, faster test run. There’s no upfront configuration that you have to do. You just install it through npm or yarn, write your test, and run &lt;strong&gt;jest&lt;/strong&gt;. Get the full details &lt;a href="https://blog.usejournal.com/jest-vs-mocha-whats-the-difference-235df75ffdf3"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mocha provides developers with a base test framework, allowing you to have options as to which assertion, mocking, and spy libraries you want to use.&lt;br&gt;
This does require some additional setup and configuration, which is a downside. However, if having complete control of your testing framework is something you want, Mocha is by far the most configurable and best choice. Get the full details &lt;a href="https://blog.usejournal.com/jest-vs-mocha-whats-the-difference-235df75ffdf3"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What we could deduce from the above explanation is that when using &lt;strong&gt;Jest&lt;/strong&gt;, you have most of the tools that are needed both for your unit and end to end tests, such as assertion and mocking abilities, while when using &lt;strong&gt;Mocha&lt;/strong&gt;, you will need to require external libraries for assertion and mocking. So, Chai can be used for assertions while Sinon can be used for mocking.&lt;/p&gt;

&lt;p&gt;I have no problem using Jest alone or using Mocha along with Chai and Sinon. My use case is wholely dependent on the project requirement. &lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;The project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I built a Mock Premier League Fixture API so as to demonstrate how you can use either &lt;strong&gt;jest&lt;/strong&gt; or &lt;strong&gt;mocha&lt;/strong&gt;. You can check out the code on github.&lt;br&gt;
Jest is used in the &lt;a href="https://github.com/victorsteven/Premier-League/tree/master"&gt;master&lt;/a&gt; branch, while Mocha/Chai/Sinon are used in the &lt;a href="https://github.com/victorsteven/Premier-League/tree/mocha-chai-sinon"&gt;mocha-chai-sinon&lt;/a&gt; branch.&lt;/p&gt;

&lt;p&gt;Get the full code:&lt;br&gt;
Using Jest &lt;a href="https://github.com/victorsteven/Premier-League/tree/master"&gt;here&lt;/a&gt;.&lt;br&gt;
Using mocha &lt;a href="https://github.com/victorsteven/Premier-League/tree/mocha-chai-sinon"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Test Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An in-memory database is used for the unit tests while a real test database is used for the end-to-end tests. Mongodb is used as the database in this project.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Jest Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is only for jest use case.&lt;br&gt;
First, install jest and &lt;a class="mentioned-user" href="https://dev.to/shelf"&gt;@shelf&lt;/a&gt;/jest-mongodb and supertest(used for end-to-end tests)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev jest supertest @shelf/jest-mongodb 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create a &lt;strong&gt;jest.config.js&lt;/strong&gt; file in the root directory and specify the preset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@shelf/jest-mongodb&lt;/span&gt;&lt;span class="dl"&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;p&gt;Next we, create &lt;strong&gt;jest-mongodb-config.js&lt;/strong&gt; file which is used to configure our in-memory db for unit tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mongodbMemoryServerOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4.0.2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Version of MongoDB&lt;/span&gt;
      &lt;span class="na"&gt;skipMD5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;autoStart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;p&gt;We then need to setup database and seed data. Create the &lt;strong&gt;test-setup&lt;/strong&gt; directory and the &lt;strong&gt;db-config.js&lt;/strong&gt; and &lt;strong&gt;seed.js&lt;/strong&gt; files&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;db-config.js&lt;/strong&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="c1"&gt;//in-memory db used only in unit testing&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongooseOpts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;useNewUrlParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;autoReconnect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reconnectTries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reconnectInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__MONGO_URI__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mongooseOpts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;//Drop database, close the connection. &lt;/span&gt;
&lt;span class="c1"&gt;//Used by both unit and e2e tests&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dropDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="c1"&gt;//Remove all the data for all db collections. &lt;/span&gt;
&lt;span class="c1"&gt;//Used by both unit and e2e tests&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteMany&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;p&gt;The file above is self-explanatory. You can checkout out the seed.js file in the &lt;a href="https://github.com/victorsteven/Premier-League"&gt;repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last setup using jest is to specify the script to run in the &lt;strong&gt;package.json&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cross-env NODE_ENV=test jest --runInBand  --testTimeout=20000"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;cross-env&lt;/strong&gt; enable us run scripts that set and use environment variables across platforms. As seen above, it enabled us set our environment to &lt;strong&gt;test&lt;/strong&gt;. Install using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install cross-env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To disable concurrency (parallel execution) in Jest, we specify the &lt;strong&gt;runInBand&lt;/strong&gt; flag so as to make Jest run tests sequentially.&lt;br&gt;
We then specified a timeout of 20 seconds (20000ms).&lt;/p&gt;

&lt;p&gt;Specify a key in the &lt;strong&gt;package.json&lt;/strong&gt; file to tell jest about the test environment, files to ignore while testing and that test output should be in verbose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"jest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"testEnvironment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coveragePathIgnorePatterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"/node_modules/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"/dist/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"verbose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Mocha, Chai and Sinon Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is for Mocha, Chai, and Sinon users.&lt;br&gt;
First, install mocha, chai and sinon, and their extensions that will be used in the unit and end-to-end tests&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev mocha chai chai-as-promised chai-http sinon @sinonjs/referee-sinon sinon-chai  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For unit testing, we will need to install a mongodb memory server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install mongodb-memory-server --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then install &lt;strong&gt;nyc&lt;/strong&gt; which is the &lt;strong&gt;Istanbul&lt;/strong&gt; command-line interface for code coverage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install nyc --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We next setup database and seed data. Create the &lt;strong&gt;test-setup&lt;/strong&gt; directory and the &lt;strong&gt;db-config.js&lt;/strong&gt;&lt;br&gt;
The content of the &lt;strong&gt;db-config.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MongoMemoryServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb-memory-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MongoMemoryServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;//in-memory db for unit test&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getConnectionString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongooseOpts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;useNewUrlParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;autoReconnect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;reconnectTries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;reconnectInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mongooseOpts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;span class="c1"&gt;//works perfectly for unit test in-memory db&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dropDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="c1"&gt;//Remove all the data for all db collections. &lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteMany&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;p&gt;We use the  &lt;strong&gt;mongodb-memory-server&lt;/strong&gt; library to setup in-memory db for unit tests. This can also be used for &lt;strong&gt;jest&lt;/strong&gt; but we followed a different approach, as seen in the &lt;strong&gt;jest setup&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next, create the &lt;strong&gt;mocha.env.js&lt;/strong&gt; file which is used to tell our test the environment to run on. We used &lt;strong&gt;cross-env&lt;/strong&gt; to take care of this in the jest configuration above. I tried using that with mocha, but I didn't give the desired result.&lt;br&gt;
So the &lt;strong&gt;mocha.env.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the script file in package.json, where we will require the above file, use babel to convert ES6 to ES5, specify the directories mocha will look for when running our tests and set a timeout of 20seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nyc --require @babel/register --require ./mocha.env.js  mocha ./api/**/*.test.js --timeout 20000 --exit"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;An Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Remember to stick to using one test framework(jest or mocha) per project.&lt;/p&gt;

&lt;p&gt;Let's consider the signup/create user flow.&lt;br&gt;
We have the &lt;strong&gt;user.controller.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerValidate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We took the user's input from the request, called the &lt;strong&gt;registerValidate&lt;/strong&gt; function from the &lt;strong&gt;validate.js&lt;/strong&gt; file located in the &lt;strong&gt;utils&lt;/strong&gt; directory in the &lt;a href="https://github.com/victorsteven/Premier-League"&gt;repo&lt;/a&gt;, we then called the &lt;strong&gt;createUser&lt;/strong&gt; method passing in the user to create. &lt;strong&gt;createUser&lt;/strong&gt; is a method defined in the  &lt;strong&gt;user.service.js&lt;/strong&gt; file, which is passed into our controller using dependency injection. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;user.service.js&lt;/strong&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;//check if the user already exists&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;//assign role:&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="c1"&gt;//create the user&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createdUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createdUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//return user details except email and password:&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;role&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;publicUser&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Unit Tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's now wire our test cases for the files above.&lt;br&gt;
To achieve unit test, we will need to mock external function/method calls.&lt;br&gt;
From the &lt;strong&gt;user.controller.js&lt;/strong&gt; file above, the &lt;strong&gt;createUser&lt;/strong&gt; controller method we will mock the calls to &lt;strong&gt;registerValidate&lt;/strong&gt; function, &lt;strong&gt;createUser&lt;/strong&gt; service method, the response and the status that is sent back to the client.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mzeWvy5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eigacanc4pzsgbomin8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mzeWvy5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/eigacanc4pzsgbomin8e.png" alt="Alt Text" width="271" height="50"&gt;&lt;/a&gt;&lt;br&gt;
Looking at the &lt;strong&gt;user.service.js&lt;/strong&gt; file, the createUser service method called an external function, &lt;strong&gt;hashPassword&lt;/strong&gt; to help us hash the password. To achieve unit testing, we will mock that.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJOjQ-cb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6c12px2jwmxyxs6ki799.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJOjQ-cb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6c12px2jwmxyxs6ki799.png" alt="Alt Text" width="251" height="47"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Using Jest&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;a. Controller &lt;strong&gt;createUser&lt;/strong&gt; method.&lt;br&gt;
To mock the response and the status, we will use &lt;strong&gt;jest.fn()&lt;/strong&gt;, which is used to create a jest mock object.&lt;br&gt;
We use &lt;strong&gt;jest.spyOn&lt;/strong&gt; to mock the &lt;strong&gt;registerValidate&lt;/strong&gt; and &lt;strong&gt;createUser&lt;/strong&gt; methods. It is used to mock just a function/method in a given object or class.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;user.controller.test.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/user.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserController&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
      &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clearAllMocks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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;span class="c1"&gt;//since validate is foreign, we have to mock it to achieve unit test. We are only mocking the 'registerValidate' function&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorStub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;registerValidate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;//no input error&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stubValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="c1"&gt;//We also mock the 'createUser' service method&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stubValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;userController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorStub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stubValue&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;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can check out the &lt;a href="https://github.com/victorsteven/Premier-League"&gt;repo&lt;/a&gt; for unsuccessful user creation tests.&lt;br&gt;
So, we tested only the &lt;strong&gt;createUser&lt;/strong&gt; controller method and mocked all other methods that it depended on, with the help of jest mock and spies libraries. So we can say that the &lt;strong&gt;createUser&lt;/strong&gt; controller method is unit tested🔥. &lt;/p&gt;

&lt;p&gt;b. Service &lt;strong&gt;createUser&lt;/strong&gt; method.&lt;br&gt;
Instead of hitting a real database, we will use the in-memory database we had earlier set up in order to achieve unit tests in the services.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;user.service.test.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/seed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/db-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;

&lt;span class="c1"&gt;//Connect to in-memory db before test&lt;/span&gt;
&lt;span class="nx"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;seededUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Clear all test data after every test.&lt;/span&gt;
&lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Remove and close the db and server.&lt;/span&gt;
&lt;span class="nx"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should not create a new user if record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;frank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a new user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kate@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;//'hashPassword' is a  dependency, so we mock it, and return any value we want&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashPass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hashPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ksjndfklsndflksdmlfksdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashPass&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&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;p&gt;We have both a failure and a successful test case. For the failure test, we first seeded our in-memory db with a user, then tried to insert a record that has the same email as the seeded user. We expected that test to throw an error, which it did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also tested for a successful insertion.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Using Mocha/Chai/Sinon&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We will mock external methods and functions using sinon's &lt;strong&gt;stub&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;a. Controller &lt;strong&gt;createUser&lt;/strong&gt; method.&lt;br&gt;
The &lt;strong&gt;user.controller.test.js&lt;/strong&gt; file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chai&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sinonChai&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon-chai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/user.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chai-as-promised&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nx"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sinonChai&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chai&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserController&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sandbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createSandbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mockResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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;span class="c1"&gt;//since validate is foreign, we have to mock it to achieve unit test. We are only mocking the 'registerValidate' function&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errorStub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;registerValidate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt; &lt;span class="c1"&gt;//no input error&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stubValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stubValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;userController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorStub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledOnce&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledOnce&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledOnce&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledOnce&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;been&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledWith&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stubValue&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;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;As seen above, the beforeEach() hook, we created a sinon sandbox. Sandboxes remove the need to keep track of every fake created, which greatly simplifies cleanup. It becomes useful when other tests are added, as shown in the &lt;a href="https://github.com/victorsteven/Premier-League/blob/master/api/controllers/user.controller.test.js"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;b. Service &lt;strong&gt;createUser&lt;/strong&gt; method&lt;br&gt;
The &lt;strong&gt;user.service.test.js&lt;/strong&gt; file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chai&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sinon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../utils/password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/seed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/db-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chai-as-promised&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chai&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UserService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

  &lt;span class="c1"&gt;//Connect to in-memory db &lt;/span&gt;
  &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;seededUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;sandbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sinon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createSandbox&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;//Clear all test data after every test.&lt;/span&gt;
  &lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;//Remove and close the db and server.&lt;/span&gt;
  &lt;span class="nx"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should not create a new user if record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;frank&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rejectedWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a new user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kate@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;//'hashPassword' is a  dependency, so we mock it&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashPass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sandbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hashPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ksjndfklsndflksdmlfksdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashPass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calledOnce&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&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;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can see that we have two tests in the above suite. One failure and one success. For the failure test, we seeded our in-memory db and tried to add a record with the same email like the one in the db. You might need to pay attention to this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rejectedWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We expected the promise to be rejected with an error. This was made possible using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chai-as-promised&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have used the create user functionality to see how we can write unit tests in our &lt;strong&gt;controllers&lt;/strong&gt; and &lt;strong&gt;services&lt;/strong&gt;, using either &lt;strong&gt;jest&lt;/strong&gt; or &lt;strong&gt;mocha&lt;/strong&gt; test framework. Do well to check the &lt;a href="https://github.com/victorsteven/Premier-League"&gt;repo&lt;/a&gt; for the entire test suites.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;End To End Tests(e2e)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For our e2e tests, we won't be mocking any dependency. We want to really test an entire functionality that cuts across different layers at a goal. This is essential as help gives us confidence that all layers in our api as working as expected. We will only see an example when &lt;strong&gt;jest&lt;/strong&gt; is used.  You can check the &lt;strong&gt;mocha-chai-sinon&lt;/strong&gt; &lt;a href="https://github.com/victorsteven/Premier-League/tree/mocha-chai-sinon"&gt;branch&lt;/a&gt; for e2e tests using &lt;strong&gt;mocha&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The entire e2e tests inside the e2e_tests directory:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5qgaOTzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1s593no2rwvo9y93zb86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5qgaOTzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1s593no2rwvo9y93zb86.png" alt="Alt Text" width="244" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A couple of things to note, we will use the supertest installed earlier in our e2e tests. We also use a real test database. You can check the db configuration in the &lt;strong&gt;database&lt;/strong&gt; directory from the &lt;a href="https://github.com/victorsteven/Premier-League"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;User e2e test&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;supertest&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;supertest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../app/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/seed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../test-setup/db-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;

&lt;span class="nx"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;supertest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;seededUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;seedUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;//Clear all test data after every test.&lt;/span&gt;
&lt;span class="nx"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;clearDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;//Remove and close the test db and server.&lt;/span&gt;
&lt;span class="nx"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;closeDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User E2E&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST /user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;victor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;victor@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;

      &lt;span class="c1"&gt;//we didnt return email and password, so we wont assert for them&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;//we can query the db to confirm the record&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createdUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createdUser&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeDefined&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createdUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;//since our password is hashed:&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createdUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should not create a user if the record already exist.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chikodi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;seededUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//a record that already exist&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;record already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;


    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should not create a user if validation fails&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//the name is required&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;victorexample.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//invalid email&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;//the password should be atleast 6 characters&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a valid name is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a valid email is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a valid password with atleast 6 characters is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="p"&gt;]&lt;/span&gt;                  
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errors&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above, we have two failure tests and one successful test case.&lt;br&gt;
We created a fake server so that we don't listen to the real server and mess it up. After the test, we close the fake server.&lt;br&gt;
You can check how this test is done using mocha, chai, and chai-http from the &lt;a href="https://github.com/victorsteven/Premier-League/tree/mocha-chai-sinon"&gt;mocha-chai-sinon&lt;/a&gt; branch.&lt;/p&gt;

&lt;p&gt;A sample output of the project entire test suites:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ffdEBxWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u6x7n1h5dn4vhxhtm03t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ffdEBxWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/u6x7n1h5dn4vhxhtm03t.png" alt="Alt Text" width="880" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With a few examples, we have explored use cases when using &lt;strong&gt;jest&lt;/strong&gt; and &lt;strong&gt;mocha&lt;/strong&gt;. These are some of my findings:&lt;br&gt;
a. Declaring test hooks can be defined both inside and outside the &lt;strong&gt;describe&lt;/strong&gt; block when using &lt;strong&gt;jest&lt;/strong&gt;. This is not the case when using mocha, as test hooks are defined inside a &lt;strong&gt;describe&lt;/strong&gt; block.&lt;br&gt;
b. Jest has &lt;strong&gt;instabul&lt;/strong&gt; built it for test coverage by using the &lt;strong&gt;--coverage&lt;/strong&gt; flag when running tests. This is not the case with &lt;strong&gt;mocha&lt;/strong&gt; which requires an external package &lt;strong&gt;nyc&lt;/strong&gt;(which is Istanbul command line interface) for test coverage.&lt;br&gt;
c. Jest has most of the test tools built-in, hence you can hit the ground running immediately. Mocha provides you a base test framework and allows you to use libraries of your choice for assertions, spies, and mocks.&lt;/p&gt;

&lt;p&gt;Get the full code:&lt;br&gt;
Using Jest &lt;a href="https://github.com/victorsteven/Premier-League/tree/master"&gt;here&lt;/a&gt;.&lt;br&gt;
Using mocha &lt;a href="https://github.com/victorsteven/Premier-League/tree/mocha-chai-sinon"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Testing.&lt;/p&gt;

&lt;p&gt;You can follow on &lt;a href="https://twitter.com/stevensunflash"&gt;twitter&lt;/a&gt; for new notifications.&lt;/p&gt;

</description>
      <category>node</category>
      <category>jest</category>
      <category>mocha</category>
      <category>test</category>
    </item>
    <item>
      <title>Using Domain-Driven Design(DDD)in Golang</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Sat, 22 Feb 2020 17:49:07 +0000</pubDate>
      <link>https://dev.to/stevensunflash/using-domain-driven-design-ddd-in-golang-3ee5</link>
      <guid>https://dev.to/stevensunflash/using-domain-driven-design-ddd-in-golang-3ee5</guid>
      <description>&lt;p&gt;Domain-Driven Design pattern is the talk of the town today. &lt;br&gt;
Domain-Driven Design(DDD) is an approach to software development that simplifies the complexity developers face by connecting the implementation to an evolving model.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Note&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This is not an article that explains the "ideal" way to implement DDD in Golang because the author is no way an expert on it. This article is rather the author's understanding of DDD based on his research. The author &lt;br&gt;
will be very grateful to contributions on how to improve this article.&lt;/strong&gt;&lt;br&gt;
Check the github repo for the updated code:&lt;br&gt;
&lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;https://github.com/victorsteven/food-app-server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why DDD?&lt;br&gt;
The following are the reasons to consider using DDD:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide principles &amp;amp; patterns to solve difficult problems&lt;/li&gt;
&lt;li&gt;Base complex designs on a model of the domain&lt;/li&gt;
&lt;li&gt;Initiate a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses domain problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea of Domain-Driven Design was inverted by &lt;a href="https://twitter.com/ericevans0" rel="noopener noreferrer"&gt;Eric Evans&lt;/a&gt;. He wrote about it in a book which you can find some of the highlights &lt;a href="https://www.goodreads.com/work/quotes/173058-domain-driven-design-tackling-complexity-in-the-heart-of-software" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DDD comprises of 4 Layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Domain: This is where the domain and business logic of the application is defined.&lt;/li&gt;
&lt;li&gt;Infrastructure:  This layer consists of everything that exists independently of our application: external libraries, database engines, and so on.&lt;/li&gt;
&lt;li&gt;Application: This layer serves as a passage between the domain and the interface layer. The sends the requests from the interface layer to the domain layer, which processes it and returns a response.&lt;/li&gt;
&lt;li&gt;Interface: This layer holds everything that interacts with other systems, such as web services, RMI interfaces or web applications, and batch processing frontends.&lt;/li&gt;
&lt;/ol&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%2Fzxy4sge2vsk0pv53ik9v.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%2Fzxy4sge2vsk0pv53ik9v.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
To have a thorough definition of terms of each layer, please refer to &lt;a href="http://dddsample.sourceforge.net/architecture.html" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Let's get started.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We are going to build a food recommendation API.&lt;/p&gt;

&lt;p&gt;You can get the code if you don't have all the time to read.&lt;br&gt;
Get the API code &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Get the Frontend code &lt;a href="https://github.com/victorsteven/food-app-client" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The very first thing to do is to initialize the dependency management. We will be using &lt;strong&gt;go.mod&lt;/strong&gt;. From the root directory(path: food-app/), initialize &lt;strong&gt;go.mod&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
 &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;food&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;

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

&lt;/div&gt;
&lt;p&gt;This is how the project is going to be organized:&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%2F603kx3hs78n8s7aopood.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%2F603kx3hs78n8s7aopood.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this application, we will use &lt;strong&gt;postgres&lt;/strong&gt; and &lt;strong&gt;redis&lt;/strong&gt; databases to persist data. We will define a .env file that has connection information.&lt;br&gt;
The &lt;strong&gt;.env&lt;/strong&gt; file looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
This file should be located in the root directory(path: food-app/)
&lt;h3&gt;
  
  
  &lt;strong&gt;Domain Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will consider the domain first. &lt;br&gt;
The domain has several patterns. Some of which are:&lt;br&gt;
Entity, Value, Repository, Service, and so on.&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%2Fl8ux2zry0gpcf3moy16o.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%2Fl8ux2zry0gpcf3moy16o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the application we are building here is a simple one, we consider just two &lt;strong&gt;domain&lt;/strong&gt; patterns: &lt;strong&gt;entity&lt;/strong&gt; and &lt;strong&gt;repository&lt;/strong&gt;. &lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Entity&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is where we define the "Schema" of things.&lt;br&gt;
For example, we can define a user's struct. See the &lt;strong&gt;entity&lt;/strong&gt; as the blueprint to the domain.&lt;/p&gt;


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


&lt;p&gt;From the above file, the user's struct is defined that contains the user information, we also added helper functions that will validate and sanitize inputs. A Hash method is called that helps hash password. That is defined in the  &lt;strong&gt;infrastructure&lt;/strong&gt; layer. &lt;br&gt;
&lt;a href="http://gorm.io" rel="noopener noreferrer"&gt;Gorm&lt;/a&gt; is used as the ORM of choice.&lt;/p&gt;

&lt;p&gt;The same approach is taken when defining the food entity. You can look up the &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Repository&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The repository defines a collection of methods that the infrastructure implements. This gives a vivid picture of the number of methods that interact with a given database or a third-party API.&lt;/p&gt;

&lt;p&gt;The user's repository will look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The methods are defined in an interface. These methods will later be implemented in the infrastructure layer.&lt;/p&gt;

&lt;p&gt;Almost the same applies to the food repository &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Infrastructure Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This layer implements the methods defined in the repository. The methods interact with the database or a third-party API. This article will only consider database interaction.&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%2Fas8nb3zr2oq46tjsrgjq.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%2Fas8nb3zr2oq46tjsrgjq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see how the user's repository implementation looks like:&lt;/p&gt;


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


&lt;p&gt;Well, you can see that we implemented the methods that were defined in the &lt;strong&gt;repository&lt;/strong&gt;. This was made possible using the &lt;strong&gt;UserRepo&lt;/strong&gt; struct which implements the &lt;strong&gt;UserRepository&lt;/strong&gt; interface, as seen in this line:&lt;/p&gt;

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

//UserRepo implements the repository.UserRepository interface
var _ repository.UserRepository = &amp;amp;UserRepo{}


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

&lt;/div&gt;
&lt;p&gt;You can check the repository on how the food repository was implemented &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, let's configure our database by creating the &lt;strong&gt;db.go&lt;/strong&gt; file with the content:&lt;/p&gt;


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

&lt;p&gt;&lt;br&gt;&lt;br&gt;
From the above file, we defined the &lt;strong&gt;Repositories&lt;/strong&gt; struct which holds all the repositories in the application. We have the user and the food repositories. The Repositories also have a db instance, which is passed to the "constructors" of user and food(that is, NewUserRepository and NewFoodRepository). &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Application Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have successfully defined the API business logic in our &lt;strong&gt;domain&lt;/strong&gt;. The &lt;strong&gt;application&lt;/strong&gt; connects the &lt;strong&gt;domain&lt;/strong&gt; and the &lt;strong&gt;interfaces&lt;/strong&gt; layers.&lt;/p&gt;

&lt;p&gt;We will only consider the user's application. You can check out that of the food in the &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the user's application:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The above have methods to save and retrieve user data. The UserApp struct has the &lt;strong&gt;UserRepository&lt;/strong&gt; interface, which made it possible to call the &lt;strong&gt;user repository&lt;/strong&gt; methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Interfaces Layer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;interfaces&lt;/strong&gt; is the layer that handles HTTP requests and responses. This is where we get incoming requests for authentication, user-related stuff, and food-related stuff.&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%2Fo6uj342ppcc7wu232xge.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%2Fo6uj342ppcc7wu232xge.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;User Handler&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We define methods for saving a user, getting all users and getting a particular user. These are found in the &lt;strong&gt;user_handler.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I want you to observe that when returning the user, we only return a &lt;strong&gt;public user&lt;/strong&gt;(which is defined in the entity). The public user does not have sensitive user details such as email and password.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Authentication Handler&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;login_handler&lt;/strong&gt; takes care of &lt;strong&gt;login&lt;/strong&gt;, &lt;strong&gt;logout&lt;/strong&gt; and &lt;strong&gt;refresh&lt;/strong&gt; token methods. Some methods defined in their respective files are called in this file. Do well to check them out in the repository following their file path.&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Food Handler&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In the &lt;strong&gt;food_handler.go&lt;/strong&gt; file, we have methods for basic &lt;strong&gt;food&lt;/strong&gt; crud: creating, reading, updating, and deleting food. The file has explanations of how the code works.&lt;/p&gt;


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


&lt;p&gt;Please note, when testing creating or updating food methods via the API using &lt;strong&gt;postman&lt;/strong&gt;, use &lt;strong&gt;form-data&lt;/strong&gt; not &lt;strong&gt;JSON&lt;/strong&gt;. This is because the request type is multipart/form-data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Running the Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So, let's test what we've got. We will wire up the routes, connect to the database and start the application.&lt;/p&gt;

&lt;p&gt;These will be done in the &lt;strong&gt;main.go&lt;/strong&gt; file defined in the directory root.&lt;/p&gt;


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


&lt;p&gt;The &lt;strong&gt;router(r)&lt;/strong&gt; is of type &lt;strong&gt;Engine&lt;/strong&gt; from the &lt;a href="https://github.com/gin-gonic" rel="noopener noreferrer"&gt;gin&lt;/a&gt; package we are using.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Middleware&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As seen from the above file, Some routes have restrictions. The &lt;strong&gt;AuthMiddleware&lt;/strong&gt; restricts access to an unauthenticated user. The &lt;strong&gt;CORSMiddleware&lt;/strong&gt; enables data transfer from different domains. This is useful because VueJS is used for the frontend of this application and it points to a different domain.&lt;br&gt;
The &lt;strong&gt;MaxSizeAllowed&lt;/strong&gt; middleware stops any file with size above the one the middleware specifies. Since the &lt;strong&gt;food&lt;/strong&gt; implementation requires file upload, the middleware stops files greater than the specified to be read into memory. This helps to prevent hackers from uploading an unreasonable huge file and slowing down the application. The &lt;strong&gt;middleware package&lt;/strong&gt; is defined in the &lt;strong&gt;interfaces&lt;/strong&gt; layer. &lt;/p&gt;


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


&lt;p&gt;We can now run the application using:&lt;/p&gt;


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

&lt;p&gt;go run main.go&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  &lt;strong&gt;Bonus&lt;/strong&gt;&lt;br&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vue and VueX are used to consume the API. Get the repository &lt;a href="https://github.com/victorsteven/food-app-client" rel="noopener noreferrer"&gt;here&lt;/a&gt;, You can also visit the &lt;a href="https://food-app-ddd.netlify.com" rel="noopener noreferrer"&gt;url&lt;/a&gt; and play with it.&lt;/li&gt;
&lt;li&gt;Test cases are written for most of the functionality. If you have time, you can add to it. To achieve &lt;strong&gt;unit testing&lt;/strong&gt; for each of the methods in our handler, we created a mock package(in the &lt;strong&gt;utils&lt;/strong&gt; directory) that mocks all the dependencies that are used in the handler methods.&lt;/li&gt;
&lt;li&gt;Circle CI is used for Continuous Integration.&lt;/li&gt;
&lt;li&gt;Heroku is used to deploy the API&lt;/li&gt;
&lt;li&gt;Netlify is used to deploy the Frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I hope you didn't have a hard time following this guideline on how to use DDD in when building a golang application. If you have questions or any observations, please don't hesitate to use the comment section. As said early, the author is not an expert on this. He simply wrote this article based on his use case.&lt;br&gt;
Get the API code &lt;a href="https://github.com/victorsteven/food-app-server" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Get the Frontend code &lt;a href="https://github.com/victorsteven/food-app-client" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
You can also visit the application &lt;a href="https://food-app-ddd.netlify.com" rel="noopener noreferrer"&gt;url&lt;/a&gt; and play with it.&lt;/p&gt;

&lt;p&gt;Check out other articles on medium &lt;a href="https://medium.com/@victorsteven" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can as well follow on &lt;a href="https://twitter.com/stevensunflash" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy DDDing.&lt;/p&gt;

</description>
      <category>go</category>
      <category>ddd</category>
      <category>redis</category>
      <category>postgres</category>
    </item>
    <item>
      <title>A Working Solution to JWT Creation and Invalidation in Golang</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Sat, 25 Jan 2020 22:31:41 +0000</pubDate>
      <link>https://dev.to/stevensunflash/a-working-solution-to-jwt-creation-and-invalidation-in-golang-4oe4</link>
      <guid>https://dev.to/stevensunflash/a-working-solution-to-jwt-creation-and-invalidation-in-golang-4oe4</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Before you proceed&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is &lt;strong&gt;part 1&lt;/strong&gt; of the two-part series.&lt;br&gt;
This part solely focused on creating a JWT that has no expiration date. While this seems cool, it can have security issues. For example, in the event that the JWT is hijacked. If this happens the only remedy in this article is, when the authenticated user logs out, the token will be revoked and can't be used any further(by either the hijacker or the user). So the user can obtain a new one when he login again.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;part 2&lt;/strong&gt; of this series, Two tokens will be used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short Term Token: also known as access token(usually 15 mins)&lt;/li&gt;
&lt;li&gt;Long Term Token: also known as refresh token(usually 1 week)
This approach is more secure compared to the above. 
Once the article is ready, the link will be provided here.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Whenever JWT is mentioned to be used for authentication, there is this question that is always asked by developers that have experience using it: &lt;br&gt;
&lt;strong&gt;when a user logout, what happens to the JWT?&lt;/strong&gt; &lt;br&gt;
That question is a nightmare.&lt;/p&gt;

&lt;p&gt;What this article solved: Once that user logs out, the JWT used is invalidated that very second! Without waiting for any &lt;strong&gt;expiration time&lt;/strong&gt; if any was set when the token was created.&lt;/p&gt;

&lt;p&gt;Using my Github account as a case study. I don't get logged out except I explicitly trigger the logout button. &lt;br&gt;
When using JWT, many have advocated that the token should have a short time span(15min, 20min, etc), the token should be revoked often time than not, blah, blah, blah. &lt;br&gt;
Think about it, if a token lifespan is short, say 10mins, it means, after that period, you will be logged out and need to log in again😡. Except for applications that require that(payment applications, etc), I see no reason why I should go through this pain. &lt;/p&gt;

&lt;p&gt;Solutions to the JWT discussion before now from this &lt;a href="https://dev.to/_arpy/how-to-log-out-when-using-jwt-4ajm"&gt;reading&lt;/a&gt;, include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a reasonable expiration time on tokens&lt;/li&gt;
&lt;li&gt;Delete the stored token from client-side upon log out&lt;/li&gt;
&lt;li&gt;Have DB of no longer active tokens that still have some time to live&lt;/li&gt;
&lt;li&gt;Query provided token against The &lt;strong&gt;Blacklist&lt;/strong&gt; on every authorized request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Issues from the above-mentioned solutions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What if you set the expiration of 1 hour for a JWT, then the user login, then logout after like 1 minute or so? What it means is, that JWT will be valid for an additional 59 minutes; ample time for a hacker to &lt;strong&gt;do his thing💀&lt;/strong&gt;, in the event that the user JWT was hijacked. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;About &lt;strong&gt;Blacklist&lt;/strong&gt; stuff. This is what that means: Once a user logs out, add the token he used to a &lt;strong&gt;blacklist table&lt;/strong&gt; in your database(Redis preferably). So once the user wants to perform a request that requires authentication and provides that token, then blacklist table will be queried to check if a token has been created before by that user and have not &lt;strong&gt;expired&lt;/strong&gt;, if found, don't allow the user to get away with his mischievous act, hold him right there✊. &lt;br&gt;
While this approach seems cool, it has obvious downsides:&lt;br&gt;
When creating the token(during signup or login), I must specify a time when the token expires in my code. When that time elapses, the user will be forced to login again. I definitely don't want this.&lt;br&gt;
You might argue that you can create a token that does not expire right? Well, what it means is that your &lt;strong&gt;blacklist table&lt;/strong&gt; will soon have "zillions" of rows of JWT tokens not used by anyone, and you cannot afford to delete any because a user might wait patiently and reuse a token he has been saving for like a year now, just to test the integrity of your application🧐.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This is what this article is all about:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We want a type of application in which the user does not try to access his account after a few minutes or hours and discover that he is logged out because we are trying to protect them from hackers💀. 
Don't get me wrong, it all depends on the time of application. For instance, my banking application logs me out after say 5min of inactivity, which is a good use case.&lt;/li&gt;
&lt;li&gt;We want an application in which, when the user chooses to logout, he does so, and can't try to use that same JWT he used before logging out for any authenticated request. He should not be allowed.&lt;/li&gt;
&lt;li&gt;We don't an application that has "zillions" of rows of blacklisted JWTs. Total no! I mean, why waste resources?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So this is what we want:&lt;br&gt;
&lt;strong&gt;An application that can keep the user logged in forever except the user chooses to explicitly logout. I don't know about you, but this is how I &lt;br&gt;
use my Twitter, Github, and so on.&lt;/strong&gt;&lt;br&gt;
To achieve this in your application, this piece is for you. Especially when you want to use JWT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the trick I used:&lt;/strong&gt;&lt;br&gt;
I created a database table called &lt;strong&gt;auths&lt;/strong&gt;, the table has three columns: &lt;strong&gt;id&lt;/strong&gt;, &lt;strong&gt;user_id&lt;/strong&gt; and &lt;strong&gt;auth_uuid&lt;/strong&gt;. Pay attention to the &lt;strong&gt;auth_uuid&lt;/strong&gt;. It is created from &lt;strong&gt;uuid&lt;/strong&gt;. UUID stands for a &lt;strong&gt;universally unique identifier&lt;/strong&gt;. When a user login, a JWT is created. The &lt;strong&gt;user_id&lt;/strong&gt; and &lt;strong&gt;auth_uuid&lt;/strong&gt; are used as &lt;strong&gt;claims for that JWT. The **user_id&lt;/strong&gt; is the id of the user who attempts to login, while the &lt;strong&gt;auth_uuid&lt;/strong&gt; is created using a helper package called: &lt;a href="https://github.com/twinj/uuid" rel="noopener noreferrer"&gt;twinj&lt;/a&gt;. When a user logs out, the created row(of the user_id and the auth_uuid is deleted from the auths table). What it now means is, though the JWT has not expired, it cannot be used to make any further requests on behalf of that user. &lt;br&gt;
Reason: because part of its &lt;strong&gt;claims&lt;/strong&gt; are deleted. For that user to make any authenticated request again, he needs to login, which will create a new JWT for him then also a new row is added to the &lt;strong&gt;auths&lt;/strong&gt; table, with the &lt;strong&gt;user_id&lt;/strong&gt; and a brand new &lt;strong&gt;auth_uuid&lt;/strong&gt;. Take note that a new &lt;strong&gt;uuid&lt;/strong&gt; is created for each JWT according to the code implementation you will below.&lt;br&gt;
If what was explained above is not clear, please look at the example below where it was demonstrated. &lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Building&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider a simple &lt;strong&gt;Todo Restful API with Authentication&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Basic StepUp&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;a. From any location, you prefer in your computer, create a directory called &lt;strong&gt;manage-jwt&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 mkdir manage-jwt

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

&lt;/div&gt;
&lt;p&gt;b. Change to that directory &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 manage-jwt

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

&lt;/div&gt;
&lt;p&gt;Then initialize &lt;strong&gt;go modules&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
 &lt;span class="n"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;

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

&lt;/div&gt;
&lt;p&gt;c. Environmental variables. &lt;br&gt;
We will store all our environmental variables in &lt;strong&gt;.env&lt;/strong&gt; file.&lt;br&gt;
From the root directory, create the .env file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 .env

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

&lt;/div&gt;

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


&lt;h3&gt;
  
  
  &lt;strong&gt;Creating JWT&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From your project root directory(path: manage-jwt/), create the &lt;strong&gt;auth&lt;/strong&gt; package(directory), then the &lt;strong&gt;auth.go&lt;/strong&gt; file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 auth

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

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 auth &amp;amp;&amp;amp; touch auth.go

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

&lt;/div&gt;

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



&lt;p&gt;From the file above, we created the JWT with the &lt;strong&gt;UserId&lt;/strong&gt; and a &lt;strong&gt;AuthUuid&lt;/strong&gt;, as seen in the &lt;strong&gt;AuthDetails&lt;/strong&gt; struct. We also have functions that verify the token and extract the &lt;strong&gt;UserId&lt;/strong&gt; and the &lt;strong&gt;AuthUuid&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Wiring the Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From the root directory, create the &lt;strong&gt;model&lt;/strong&gt; directory. This is where we will have our database initialization and all database related stuff.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 model

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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;a. Let's create the base_model.go file.&lt;/strong&gt;  &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 model &amp;amp;&amp;amp; touch base_model.go

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

&lt;/div&gt;

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

&lt;p&gt;&lt;br&gt;&lt;br&gt;
From the above file, we have the &lt;strong&gt;Initialize&lt;/strong&gt; method and an interface that is a collection of our model methods we will define soon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. Create the user model&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 touch user.go 

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

&lt;/div&gt;

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



&lt;p&gt;We have methods that validate the email, create a user and get a user by email.&lt;br&gt;
Since the sole aim of this article is about &lt;strong&gt;jwt&lt;/strong&gt;, we left implementation as basic as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. Create the todo model&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 todo.go

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

&lt;/div&gt;

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
As seen in the above file, we just have the &lt;strong&gt;CreateTodo&lt;/strong&gt; model, since we are focused on JWT.

&lt;p&gt;&lt;strong&gt;d. Create the auth_uuid model&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 auth_uuid.go

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

&lt;/div&gt;

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


&lt;p&gt;We functionalities to &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;get&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt; the &lt;strong&gt;uuid&lt;/strong&gt; and the &lt;strong&gt;user id&lt;/strong&gt; associated with the &lt;strong&gt;jwt&lt;/strong&gt;. For instance, the &lt;strong&gt;CreateAuth&lt;/strong&gt; method is used in the &lt;strong&gt;Login&lt;/strong&gt; controller function(this will be defined later), the &lt;strong&gt;auth&lt;/strong&gt; created have the &lt;strong&gt;AuthUuid&lt;/strong&gt; and the &lt;strong&gt;UserId&lt;/strong&gt;. These are then used as &lt;strong&gt;claims&lt;/strong&gt; when creating the JWT.&lt;br&gt;
Whenever a request is made that requires authentication, the &lt;strong&gt;FetchAuth&lt;/strong&gt; method is called, which lookup the &lt;strong&gt;auths&lt;/strong&gt; table and check for the &lt;strong&gt;auth_uuid&lt;/strong&gt; and the &lt;strong&gt;user_id&lt;/strong&gt;. If they exist, the next line of action is taken(such as Creating a Todo, Logging out the user, etc).&lt;br&gt;
The &lt;strong&gt;DeleteAuth&lt;/strong&gt; method is used to delete the &lt;strong&gt;auth_uuid&lt;/strong&gt; and &lt;strong&gt;user id&lt;/strong&gt; from the &lt;strong&gt;auths&lt;/strong&gt; table. This happens during logout, thus, rendering that JWT &lt;strong&gt;useless😪&lt;/strong&gt; because it cannot be used for any other request. Ever!.&lt;/p&gt;

&lt;p&gt;Take note that the JWT is not deleted. It still exists, but it is invalid because the &lt;strong&gt;claims&lt;/strong&gt; used to form it are no more. What actually made this possible is the &lt;strong&gt;uuid&lt;/strong&gt;. Since the uuid is unique at its creation, there is little or no chance of having the same &lt;strong&gt;uuid&lt;/strong&gt; in &lt;strong&gt;auths&lt;/strong&gt; table. Even if that eventually happens, the &lt;strong&gt;user id&lt;/strong&gt; is ever unique. We can't two or more same &lt;strong&gt;user id&lt;/strong&gt; in the &lt;strong&gt;auths&lt;/strong&gt; table. &lt;br&gt;
This is how the uuid table looks like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;user_id&lt;/th&gt;
&lt;th&gt;auth_uuid&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&lt;/td&gt;
&lt;td&gt;83b09612-9dfc-4c1d-8f7d-a589acec7081&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-----&lt;/td&gt;
&lt;td&gt;----------&lt;/td&gt;
&lt;td&gt;---------------------------------------&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;14033612-df45-sdf3-137d-dfsdfd32243d&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, when the &lt;strong&gt;DeleteAuth&lt;/strong&gt; method is called, the row that matches the parameters provided is deleted. Then no further request can be carried out with that JWT again because the &lt;strong&gt;auths&lt;/strong&gt; table will always be checked👨‍✈️.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Wire up the Signin Service&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before any authenticated request is made, the user needs to the signed in. This is where the &lt;strong&gt;CreateToken&lt;/strong&gt; function from the &lt;strong&gt;auth&lt;/strong&gt; package is called.&lt;/p&gt;

&lt;p&gt;From the root directory, create the &lt;strong&gt;service&lt;/strong&gt; directory:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 service

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

&lt;/div&gt;
&lt;p&gt;Then, create the &lt;strong&gt;signin_service.go&lt;/strong&gt; file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 service &amp;amp;&amp;amp; touch signin_service.go

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

&lt;/div&gt;

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


&lt;p&gt;This would simply have been done without an interface. The purpose of defining the method in an interface is to enable us to mock it when writing test cases.&lt;br&gt;
Observe that we passed as parameter the &lt;strong&gt;AuthDetails&lt;/strong&gt; struct which defines the &lt;strong&gt;auth_uuid&lt;/strong&gt; and the &lt;strong&gt;user id&lt;/strong&gt;; which are used as &lt;strong&gt;claims&lt;/strong&gt; when creating JWT.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Wire up the Controllers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From the project root(path: /manage-jwt), create the &lt;strong&gt;controller&lt;/strong&gt; directory(package).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. The User Controller&lt;/strong&gt;&lt;br&gt;
Create the &lt;strong&gt;user_controller.go&lt;/strong&gt; file&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 controller &amp;amp;&amp;amp; touch user_controller.go

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

&lt;/div&gt;

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


&lt;p&gt;Keeping things super simple, so as not to distract the main purpose of the article. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. The Login Controller&lt;/strong&gt;&lt;br&gt;
A user can login after he has signed up(been created).&lt;br&gt;
Create the &lt;strong&gt;login_controller.go&lt;/strong&gt; file&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 touch login_controller.go 

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

&lt;/div&gt;

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


&lt;p&gt;As seen in the file above, we have both the &lt;strong&gt;Login&lt;/strong&gt; and the &lt;strong&gt;LogOut&lt;/strong&gt; functions. &lt;br&gt;
Observe in the &lt;strong&gt;Login&lt;/strong&gt; function that we created a new &lt;strong&gt;row&lt;/strong&gt; in the &lt;strong&gt;auths&lt;/strong&gt; table when we called &lt;strong&gt;CreateAuth&lt;/strong&gt; method, we then passed its return value to the &lt;strong&gt;SignIn&lt;/strong&gt; method, which calls the &lt;strong&gt;CreateToken&lt;/strong&gt; function.&lt;br&gt;
So now, we have a JWT and a &lt;strong&gt;row&lt;/strong&gt; in the &lt;strong&gt;auths&lt;/strong&gt; table that has the &lt;strong&gt;auths&lt;/strong&gt; and the &lt;strong&gt;user id&lt;/strong&gt; used as claims when creating the token.&lt;/p&gt;

&lt;p&gt;From the &lt;strong&gt;LogOut&lt;/strong&gt; function, called the &lt;strong&gt;DeleteAuth&lt;/strong&gt; method that deleted that &lt;strong&gt;row&lt;/strong&gt; created in the &lt;strong&gt;auths&lt;/strong&gt; table, thus rendering the JWT useless. &lt;/p&gt;

&lt;p&gt;Note: Remember that before you logout, you must be authenticated, so you must add to the header of your request a valid JWT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. The Todo Controller&lt;/strong&gt;&lt;br&gt;
Create the &lt;strong&gt;todo_controller.go&lt;/strong&gt; file. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 touch todo_controller.go 

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

&lt;/div&gt;

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


&lt;p&gt;Creating a todo requires a user to be authenticated. From the &lt;strong&gt;CreateTodo&lt;/strong&gt; function, we extracted the JWT claims(particularly AuthUuid and the UserId). We then checked the validity of those by calling &lt;strong&gt;FetchAuth&lt;/strong&gt; method. If everything goes well, we then proceed to create the todo. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Routing and Starting the Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's connect everything together and fire up the application.&lt;br&gt;
From the root directory, create the &lt;strong&gt;app&lt;/strong&gt; directory:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 app 

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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;a. Routing&lt;/strong&gt;&lt;br&gt;
Then create the &lt;strong&gt;router.go&lt;/strong&gt; file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 app &amp;amp;&amp;amp; touch router.go

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

&lt;/div&gt;
&lt;p&gt;Observe that we called a middleware we have not created yet and we used a &lt;strong&gt;router&lt;/strong&gt;. We will create these shortly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. The StartApp function&lt;/strong&gt;&lt;br&gt;
Still, in the &lt;strong&gt;app&lt;/strong&gt; directory, create the &lt;strong&gt;app.go&lt;/strong&gt; file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 touch app.go

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

&lt;/div&gt;

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


&lt;p&gt;The above file defined the &lt;strong&gt;router&lt;/strong&gt; variable referenced in the &lt;strong&gt;router.go&lt;/strong&gt; file. It also called the &lt;strong&gt;Initialize&lt;/strong&gt; method(defined in the model), for the database connection. We called the &lt;strong&gt;route()&lt;/strong&gt; function and also started the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. The Middleware&lt;/strong&gt;&lt;br&gt;
From the root directory(path: manage-jwt/), create the &lt;strong&gt;middlewares&lt;/strong&gt; directory, then the &lt;strong&gt;middlewares.go&lt;/strong&gt; file&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 middlewares

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

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 middlewares &amp;amp;&amp;amp; middlewares.go

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

&lt;/div&gt;

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


&lt;p&gt;The &lt;strong&gt;TokenAuthMiddleware&lt;/strong&gt; function help to protect routes that require authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d. The main.go file&lt;/strong&gt;&lt;br&gt;
It is time to finally test our hard work💪. From the root directory, create the &lt;strong&gt;main.go&lt;/strong&gt; file and call the &lt;strong&gt;StartApp&lt;/strong&gt; function defined above:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 main.go

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

&lt;/div&gt;

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


&lt;p&gt;Then run:&lt;/p&gt;

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

go run main.go


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

&lt;/div&gt;

&lt;p&gt;Your app should be on fire🔥 if you followed the instructions above.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Testing with Postman&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's try our hands on some endpoints&lt;/p&gt;

&lt;p&gt;a. &lt;strong&gt;/user endpoint:&lt;/strong&gt; for creating a user(signup). Provide an email address to be signed up.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe6f6tlh9urgzvccku9w4.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe6f6tlh9urgzvccku9w4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;b. &lt;strong&gt;/login endpoint&lt;/strong&gt;&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcy9y3zup6rsdgj2ij129.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcy9y3zup6rsdgj2ij129.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;c. &lt;strong&gt;/todo endpoint:&lt;/strong&gt; Let's create a todo with the token generated above.&lt;br&gt;
This token will be added in the &lt;strong&gt;Authorization: Bearer Token&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwjinux6mvdmgs0cedmsu.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwjinux6mvdmgs0cedmsu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;d. &lt;strong&gt;/logout endpoint&lt;/strong&gt; &lt;br&gt;
To logout, you must be authenticated, so add the above token in the &lt;strong&gt;Authorization: Bearer Token&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fznpj1duqfsjp5vm1lag8.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fznpj1duqfsjp5vm1lag8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bonus&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;a. The API is deployed is to &lt;strong&gt;heroku&lt;/strong&gt;. You can test using: &lt;br&gt;
&lt;a href="https://manage-jwt.herokuapp.com" rel="noopener noreferrer"&gt;https://manage-jwt.herokuapp.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;b. &lt;strong&gt;Test Cases&lt;/strong&gt; are added for the above functionalities, get the Github repository &lt;a href="https://github.com/victorsteven/manage-jwt" rel="noopener noreferrer"&gt;here&lt;/a&gt; and run tests from the root directory using:&lt;/p&gt;

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

go test ./...


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

&lt;/div&gt;

&lt;p&gt;c. Circle CI is used for Continuous Integration.&lt;/p&gt;

&lt;p&gt;d. The application is already dockerized. You can run it on docker if you wish. Setup is found in the &lt;a href="https://github.com/victorsteven/manage-jwt" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So, there you have it. The JWT monster has been trampled on our feet, as we can invalidate it at any time if we wish.&lt;/p&gt;

&lt;p&gt;Get the repository &lt;a href="https://github.com/victorsteven/manage-jwt" rel="noopener noreferrer"&gt;here&lt;/a&gt;, which you can star to track any new update.&lt;/p&gt;

&lt;p&gt;Test the API in production using the url: &lt;a href="https://manage-jwt.herokuapp.com" rel="noopener noreferrer"&gt;https://manage-jwt.herokuapp.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Forcing JWT to be useless at will🤣.&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/stevensunflash" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; to get notified of current releases.&lt;/p&gt;

&lt;p&gt;Also, follow here on dev.to&lt;/p&gt;

&lt;p&gt;Thank you.&lt;/p&gt;

</description>
      <category>go</category>
      <category>jwt</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Using Golang Concurrency in Production</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Sun, 19 Jan 2020 23:43:04 +0000</pubDate>
      <link>https://dev.to/stevensunflash/using-golang-concurrency-in-production-3ma4</link>
      <guid>https://dev.to/stevensunflash/using-golang-concurrency-in-production-3ma4</guid>
      <description>&lt;p&gt;In this article, we will see how Asynchronous Programming is achieved in Golang using a real-world application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asynchronous&lt;/strong&gt;&lt;br&gt;
Our daily chores are filled with concurrent(asynchronous) activities.&lt;br&gt;
For instance, When making a coffee, you boil water, put the coffee in your mug, add other ingredients you need, then finally add the boiled water into the mug. Your coffee is ready. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Synchronous&lt;/strong&gt;&lt;br&gt;
From the instance above, doing this synchronously will mean you waiting for a task to be done first before undertaking another. That is, Place the water on the heater, do nothing else until that water boils. Of course, we consider this approach a total waste of our time and somewhat inefficient. &lt;br&gt;
Hence, it is inefficient to implement a feature that is asynchronous in nature synchronously. &lt;/p&gt;

&lt;p&gt;I wrote a real-world program: &lt;strong&gt;Username Lookup Application&lt;/strong&gt;, which demonstrates how asynchronous programming is utilized in making HTTP calls to different endpoints at the same time and retrieving data. This is how it works, you provide a username to look up, then that username is checked across the accounts you specify(such as Twitter, Instagram, Github, and so on). Visit the application &lt;a href="https://username-across.herokuapp.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
You can also get the code on &lt;a href="https://github.com/victorsteven/Username-Across-Platforms" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The Application Overview.
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Golang&lt;/strong&gt; is used on the backend&lt;br&gt;
&lt;strong&gt;VueJS&lt;/strong&gt; is used on the frontend&lt;br&gt;
&lt;strong&gt;Docker&lt;/strong&gt; is used to deploying on &lt;strong&gt;Heroku&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Travis&lt;/strong&gt; is used for Continous Integration&lt;/p&gt;
&lt;h1&gt;
  
  
  Steps Taken
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Step 1: Basic Setup
&lt;/h2&gt;

&lt;p&gt;Create the root folder for the project titled: &lt;strong&gt;username_across_platforms&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir username_across_platforms&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Initialize &lt;strong&gt;go modules&lt;/strong&gt; with the name of the folder created above:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go mod init username_across_platforms&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 2: Client Implementation(for HTTP calls)
&lt;/h1&gt;

&lt;p&gt;Create the &lt;strong&gt;server&lt;/strong&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir server&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Since we will be making HTTP requests to the different urls, we will need a client. Note, the client here is not the frontend. It is used for HTTP calls on the server-side. &lt;br&gt;
Inside the server package(folder), create the client package(directory):&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd server &amp;amp;&amp;amp; mkdir client&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then create &lt;strong&gt;client.go&lt;/strong&gt; inside the &lt;strong&gt;client&lt;/strong&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd client &amp;amp;&amp;amp; touch client.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;From the above file, you might be wondering why we used an interface and stuff, this will make sense to you when you see the test files. We will need to mock the &lt;strong&gt;GetValue&lt;/strong&gt; method. We can't do this except the method is defined in an interface.&lt;br&gt;
Something else I want you to observe is how we implemented the interface.&lt;br&gt;
We defined a &lt;strong&gt;clientCall&lt;/strong&gt; struct which the &lt;strong&gt;GetValue&lt;/strong&gt; method 'belongs to'. Then the struct now implements the interface in this line:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ClientCall HTTPClient = &amp;amp;clientCall{}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The struct also has the &lt;strong&gt;http.Client. This will help us replace the actual **http.Client&lt;/strong&gt; with a fake one, so we don't make a real http call while writing test cases.&lt;br&gt;
Still, in the same package, create the test file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch client_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
From the above file, we fake the real http call with the help of the &lt;strong&gt;RoundTripFunc&lt;/strong&gt;, another option you might consider is using &lt;strong&gt;httptest.Server&lt;/strong&gt;. &lt;br&gt;
You could see how the &lt;strong&gt;Transport&lt;/strong&gt; of the &lt;strong&gt;http.Client&lt;/strong&gt; is swapped with our RoundTripFunc in the &lt;strong&gt;NewFakeClient&lt;/strong&gt; function.
&lt;h2&gt;
  
  
  Step 3: Provider Implementation
&lt;/h2&gt;

&lt;p&gt;Since our client is in place with enough unit tests to back it, let us create the provider that calls the &lt;strong&gt;GetValue&lt;/strong&gt; method of the client and pass the response it obtained to a channel.&lt;br&gt;
From the &lt;strong&gt;server&lt;/strong&gt; package(directory), create the &lt;strong&gt;provider&lt;/strong&gt; package then the provider.go file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir provider&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;cd provider &amp;amp;&amp;amp; touch provider.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;As seen in the file, the &lt;strong&gt;CheckUrl&lt;/strong&gt; method is defined in an interface(because we need to mock it in the future while writing unit tests). In the method implementation, we passed the url to look up and the channel to send the response or the error if not available. The main reason we used the channel here is, the &lt;strong&gt;checkUrl&lt;/strong&gt; method will be called in a different &lt;strong&gt;goroutines&lt;/strong&gt; when will implement the &lt;strong&gt;service&lt;/strong&gt;.&lt;br&gt;
In a nutshell, the &lt;strong&gt;checkUrl&lt;/strong&gt; method checks a url, for example &lt;a href="https://twitter.com/stevensunflash" rel="noopener noreferrer"&gt;https://twitter.com/stevensunflash&lt;/a&gt;, if the url does not exist, &lt;strong&gt;cant_access_resource&lt;/strong&gt; is sent to the channel. If the url exists but the username &lt;strong&gt;stevensunflash&lt;/strong&gt; is not found, &lt;strong&gt;no_match&lt;/strong&gt; is sent to the channel, if the desired username is found, we send the &lt;strong&gt;url&lt;/strong&gt; to the channel.&lt;/p&gt;

&lt;p&gt;Now let's test the implementation.&lt;br&gt;
Create the &lt;strong&gt;provider_test.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch provider_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Observe closely that we mocked the client's &lt;strong&gt;GetValue&lt;/strong&gt; method here, this is one of the uses of defining that method in an interface from the client package. You could see how we returned the response we want from the client without hitting a real endpoint. This has also helped us achieve &lt;strong&gt;unit testing&lt;/strong&gt; on the provider without calling the real &lt;strong&gt;GetValue&lt;/strong&gt; method from the client package. How Sweet!😴
&lt;h2&gt;
  
  
  Step 4: Service Implementation(Launching Some Goroutines🚀)
&lt;/h2&gt;

&lt;p&gt;Now let's fire up some goroutines to get multiple urls responses at the same time.&lt;br&gt;
From the &lt;strong&gt;server&lt;/strong&gt; package(directory), create the &lt;strong&gt;service&lt;/strong&gt; package(directory), then the &lt;strong&gt;service.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;cd service &amp;amp;&amp;amp; touch service.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;The &lt;strong&gt;UsernameCheck&lt;/strong&gt; method receive a slice of urls to process, we already have the &lt;strong&gt;checkUrl&lt;/strong&gt; method we can use to check a url, defined in the provider's package. Now, we loop through the given urls and launch a &lt;strong&gt;goroutine&lt;/strong&gt; for each url. Remember, any response or error obtained is sent to the channel. We then get the value for each url from the channel and put it inside the &lt;strong&gt;links&lt;/strong&gt; slice.&lt;br&gt;
The result set can have three cases: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cant_access_resource&lt;/li&gt;
&lt;li&gt;no_match&lt;/li&gt;
&lt;li&gt;valid result(url)
We further filtered the links slice to get only valid urls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's write some tests to prove that our code is working.&lt;br&gt;
Create the &lt;strong&gt;service_test.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch service_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;Observe from the test that we also mocked the &lt;strong&gt;client&lt;/strong&gt; so that we don't hit the actual endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Controller Implementation(Returning the response to the caller)
&lt;/h2&gt;

&lt;p&gt;Now, let's send back an HTTP response to the caller.&lt;br&gt;
From the &lt;strong&gt;server&lt;/strong&gt; package(directory), create the &lt;strong&gt;controller&lt;/strong&gt; package(directory) and then the &lt;strong&gt;controller.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir controller&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;cd controller &amp;amp;&amp;amp; controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;Nothing fancy, the controller receives the request from the caller pass it down to the service(which concurrently uses the provider's &lt;strong&gt;checkUrls&lt;/strong&gt; method), the service passes back to the controller the urls it could process, then the controller sends the urls to the caller.&lt;/p&gt;

&lt;p&gt;Let's also test the controller, create the &lt;strong&gt;controller_test.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;As seen above to achieve unit test, we must mock the service's &lt;strong&gt;UsernameCheck&lt;/strong&gt; method, and return anything we like. We could mock the service easily with the help of the &lt;strong&gt;usernameService&lt;/strong&gt; interface.&lt;/p&gt;

&lt;p&gt;Another thing to observe from the tests is, the &lt;strong&gt;json&lt;/strong&gt; passed from the caller is of this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`["url1","url2","url3"]`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Anything outside a format like this won't work. We have the tests above to prove that.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Wiring up the application
&lt;/h2&gt;

&lt;p&gt;Though we have unit tests to prove that our application is working, lets still test it on the browser.&lt;br&gt;
From the &lt;strong&gt;server&lt;/strong&gt; package(directory), create the &lt;strong&gt;app&lt;/strong&gt; package(directory),&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir app&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;then create two files: &lt;br&gt;
-app.go&lt;br&gt;
-route.go&lt;/p&gt;

&lt;p&gt;a. app.go&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd app &amp;amp;&amp;amp; touch app.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Since we will later deploy this to &lt;a href="https://www.heroku.com" rel="noopener noreferrer"&gt;heroku&lt;/a&gt;, we checked for the &lt;strong&gt;Heroku&lt;/strong&gt; port.&lt;/p&gt;

&lt;p&gt;b. route.go&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch route.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;Observe from the route that we called a middleware we have not defined yet. This middleware will enable us to make API calls between the &lt;strong&gt;server&lt;/strong&gt; and the &lt;strong&gt;client&lt;/strong&gt;(frontend), which we will define shortly. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Middleware
&lt;/h2&gt;

&lt;p&gt;From the &lt;strong&gt;server&lt;/strong&gt; package, create the middleware package(directory), then the &lt;strong&gt;cors.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir middleware &amp;amp;&amp;amp; touch cors.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Running the app
&lt;/h2&gt;

&lt;p&gt;We now need to create the &lt;strong&gt;main.go&lt;/strong&gt; file in the &lt;strong&gt;server&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch main.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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

&lt;p&gt;We called the &lt;strong&gt;StartApp&lt;/strong&gt; function we defined in the &lt;strong&gt;app&lt;/strong&gt; package.&lt;/p&gt;

&lt;p&gt;Run the application, from the path: &lt;strong&gt;username_across_platforms/server&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;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhrjqsdovqdt2cydq12mr.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhrjqsdovqdt2cydq12mr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, run the application and use &lt;strong&gt;Postman&lt;/strong&gt; to test, or simply skip to the next step, where will use a &lt;strong&gt;vuejs&lt;/strong&gt; as our frontend.&lt;br&gt;
Remember, if you want to use &lt;strong&gt;Postman&lt;/strong&gt; or your favorite testing tool, &lt;br&gt;
pass the JSON like this: &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd0waiahi0hqc6v8g3u4a.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd0waiahi0hqc6v8g3u4a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 7: The Client(Frontend)&lt;br&gt;
All we have done thus far is &lt;strong&gt;server&lt;/strong&gt; stuff. Let's now see a beautiful representation of our hard work💪.&lt;br&gt;
We will be using &lt;strong&gt;vuejs&lt;/strong&gt;, you can also use &lt;strong&gt;reactjs&lt;/strong&gt; if you wish. After all, this is just a SPA(Single Page App)&lt;/p&gt;

&lt;p&gt;The first thing to do is install the &lt;a href="https://dev.tovue-cli"&gt;https://cli.vuejs.org/&lt;/a&gt;, if you have installed that before.&lt;/p&gt;

&lt;p&gt;From the root directory of the project(path: "username_across_platforms/"), create a new &lt;strong&gt;Vue&lt;/strong&gt; project called &lt;strong&gt;client&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;vue create client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will prompt you for some stuff, choose all default.&lt;br&gt;
When completed, enter the client(frontend) directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd client&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;💥&lt;strong&gt;Very Important&lt;/strong&gt;💥&lt;br&gt;
The application just installed already have &lt;strong&gt;git&lt;/strong&gt; initialized, remove the &lt;strong&gt;.git&lt;/strong&gt; file. From the terminal, in the path: &lt;strong&gt;username_across_platforms/client&lt;/strong&gt;, execute:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rm -rf .git&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Next step, install &lt;strong&gt;vuetify&lt;/strong&gt; we will use for the UI&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue add vuetify&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Since we will be making an api call, lets install &lt;strong&gt;axios&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add axios --save&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Great!&lt;/p&gt;

&lt;p&gt;Next, locate the &lt;strong&gt;App.vue&lt;/strong&gt; file inside the &lt;strong&gt;src&lt;/strong&gt; directory and replace the content with: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Observe above that we imported a file we have not defined(env.js). To enable us to test both on local and production, we need to inform our application at any point in time the url to use.&lt;br&gt;
In the same directory path as &lt;strong&gt;App.vue&lt;/strong&gt;, create the &lt;strong&gt;env.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, let's start the Frontend app:&lt;br&gt;
From the path: &lt;strong&gt;username_across_platforms/client&lt;/strong&gt;&lt;br&gt;
Run:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run serve&lt;/code&gt;&lt;br&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe1qfkqgaag9od4py5g1u.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe1qfkqgaag9od4py5g1u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now fire up your browser and visit: &lt;strong&gt;&lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fysuuz8zzzeq9nda5sgf6.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fysuuz8zzzeq9nda5sgf6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aww😍. You're welcome!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Hosting
&lt;/h2&gt;

&lt;p&gt;We will deploy this awesome app to &lt;a href="https://www.heroku.com" rel="noopener noreferrer"&gt;heroku&lt;/a&gt; for free. We can achieve easily using &lt;strong&gt;Docker&lt;/strong&gt;.&lt;br&gt;
From the project root (path: username_across_platforms/), create the &lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Since &lt;strong&gt;heroku&lt;/strong&gt; is used for deployment, create the &lt;strong&gt;heroku.yml&lt;/strong&gt; file, this file tells Heroku that we are dockerizing the app:&lt;br&gt;
From the root directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch heroku.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;If you have following along, push your code to github, remember to initialize git from the root directory(path: username_across_platforms/).&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing to Heroku.
&lt;/h3&gt;

&lt;p&gt;From the root directory&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the &lt;strong&gt;heroku-cli&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Login to heroku:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;heroku login&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the heroku application:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;heroku create&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tell heroku that we are deploying a container to this stack:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;heroku stack:set container&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Push to heroku:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;git commit -m "Heroku deployment"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;git push heroku master&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now visit the application when deployment is done using:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;heroku open&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Behold the application🔥 &lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I added integration tests for the server implementation&lt;/li&gt;
&lt;li&gt;I also used Travis CI for Continuous Integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get all these from the repository: &lt;br&gt;
&lt;a href="https://github.com/victorsteven/Username-Across-Platforms" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Username-Across-Platforms&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;So there you have it! A full-fledged application that uses Golang awesome concurrency feature.&lt;br&gt;
You can also visit other articles here or in my &lt;a href="https://medium.com/@victorsteven" rel="noopener noreferrer"&gt;medium account&lt;/a&gt;. &lt;br&gt;
Don't forget to follow for future articles.&lt;/p&gt;

&lt;p&gt;Get the complete code on &lt;a href="https://github.com/victorsteven/Username-Across-Platforms" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding.&lt;/p&gt;

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>docker</category>
      <category>vue</category>
    </item>
    <item>
      <title>Forum App with Golang/Gin and React/Hooks</title>
      <dc:creator>Steven Victor</dc:creator>
      <pubDate>Fri, 01 Nov 2019 10:22:24 +0000</pubDate>
      <link>https://dev.to/stevensunflash/real-world-app-with-golang-gin-and-react-hooks-44ph</link>
      <guid>https://dev.to/stevensunflash/real-world-app-with-golang-gin-and-react-hooks-44ph</guid>
      <description>&lt;p&gt;Have you been looking forward to a production application built with Golang and React? This is one.&lt;/p&gt;

&lt;p&gt;This application has an API Backend and a Frontend that consumes the API.&lt;br&gt;
The application has two repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/victorsteven/Forum-App-Go-Backend" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Forum-App-Go-Backend&lt;/a&gt; (Backend)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/victorsteven/Forum-App-React-Frontend" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Forum-App-React-Frontend&lt;/a&gt; (Frontend)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is live version of the App. You can interact with it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://seamflow.com" rel="noopener noreferrer"&gt;https://seamflow.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Technologies
&lt;/h1&gt;

&lt;p&gt;Backend Technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Golang&lt;/li&gt;
&lt;li&gt;Gin Framework&lt;/li&gt;
&lt;li&gt;GORM&lt;/li&gt;
&lt;li&gt;PostgreSQL/MySQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frontend Technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;React Hooks&lt;/li&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Devops Technologies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the above may seem overwhelming, you will see how they all work in sync.&lt;/p&gt;

&lt;p&gt;You might also like to check out my other articles about &lt;strong&gt;go&lt;/strong&gt;, &lt;strong&gt;docker&lt;/strong&gt;, &lt;strong&gt;kubernetes&lt;/strong&gt; &lt;a href="https://medium.com/@victorsteven" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;SECTION 1: Buiding the Backend&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This is backend session wired up with &lt;strong&gt;Golang&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, I will give a step by step approach to what was done.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1:  Basic Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;a. The base directory&lt;/strong&gt;&lt;br&gt;
Create the &lt;strong&gt;forum&lt;/strong&gt; directory on any path of your choice in your computer and switch to that directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        ```mkdir forum &amp;amp;&amp;amp; cd forum```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;b. Go Modules&lt;/strong&gt;&lt;br&gt;
Initialize &lt;strong&gt;go module&lt;/strong&gt;. This takes care of our dependency management. In the root directory run:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go mod init github.com/victorsteven/forum&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;As seen, I used github url, my username, and the app root directory name. You can use any convention you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. Basic Installations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will be using third party packages in this application. If you have never installed them before, you can run the following commands:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get github.com/badoux/checkmail
go get github.com/jinzhu/gorm
go get golang.org/x/crypto/bcrypt
go get github.com/dgrijalva/jwt-go
go get github.com/jinzhu/gorm/dialects/postgres
go get github.com/joho/godotenv
go get gopkg.in/go-playground/assert.v1
go get github.com/gin-contrib/cors 
go get github.com/gin-gonic/contrib
go get github.com/gin-gonic/gin
go get github.com/aws/aws-sdk-go 
go get github.com/sendgrid/sendgrid-go
go get github.com/stretchr/testify
go get github.com/twinj/uuid
github.com/matcornic/hermes/v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;d. .env file&lt;/strong&gt;&lt;br&gt;
Create and set up a &lt;strong&gt;.env&lt;/strong&gt; file in the root directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch .env&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The .env file contains the database configuration details and other details that you want to key secret. You can use the &lt;strong&gt;.env.example&lt;/strong&gt; file(from the repo) as a guide.&lt;br&gt;&lt;br&gt;
This is a sample .env file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;e. api and tests directories&lt;/strong&gt;&lt;br&gt;
Create an &lt;strong&gt;api&lt;/strong&gt; and &lt;strong&gt;tests&lt;/strong&gt; directories in the root directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir api &amp;amp;&amp;amp; mkdir tests&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Thus far, our folder structure looks like this:&lt;/p&gt;

&lt;p&gt;forum&lt;br&gt;
├── api&lt;br&gt;
├── tests&lt;br&gt;
├── .env&lt;br&gt;
└── go.mod&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2:  Wiring up the Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We will be needing about five models in this forum app:&lt;br&gt;
a. User&lt;br&gt;
b. Post&lt;br&gt;
c. Like&lt;br&gt;
d. Comment&lt;br&gt;
e. ResetPassword&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. User Model&lt;/strong&gt;&lt;br&gt;
Inside the API directory, create the &lt;strong&gt;models&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd api  &amp;amp;&amp;amp; mkdir models&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;models&lt;/strong&gt; directory, create the &lt;strong&gt;User.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd models &amp;amp;&amp;amp; touch User.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;A user can:&lt;br&gt;
  i. Signup&lt;br&gt;
  ii. Login&lt;br&gt;
  iii. Update his details&lt;br&gt;
  iv. Shutdown his account&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Post Model&lt;/strong&gt;&lt;br&gt;
  A post can be:&lt;br&gt;
  i. Created &lt;br&gt;
  ii. Updated &lt;br&gt;
  iii. Deleted&lt;br&gt;
In the models directory, create a &lt;strong&gt;Post.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Post.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. Like Model&lt;/strong&gt;&lt;br&gt;
Posts can be liked or unliked.&lt;br&gt;
A &lt;strong&gt;like&lt;/strong&gt; can be:&lt;br&gt;
i. Created&lt;br&gt;
ii. Deleted&lt;br&gt;
Create the &lt;strong&gt;Like.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Like.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. Comment Model&lt;/strong&gt;&lt;br&gt;
A post can have comments. &lt;br&gt;
Comment can be:&lt;br&gt;
   i. Created&lt;br&gt;
   ii. Updated&lt;br&gt;
   iii. Deleted&lt;br&gt;
  Create the &lt;em&gt;Comment.go&lt;/em&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Comment.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. ResetPassword Model&lt;/strong&gt;&lt;br&gt;
A user might forget his/her password. When this happens, they can request to change to a new one. A notification will be sent to their email address with instructions to create a new password.&lt;br&gt;
In the &lt;strong&gt;models&lt;/strong&gt; directory, create the &lt;strong&gt;ResetPassword.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch ResetPassword.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3:  Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;a. Password Security&lt;/strong&gt;&lt;br&gt;
Observe in the &lt;em&gt;User.go&lt;/em&gt; file, that before a password is saved in our database, it must first be hashed. We called a function to help us do that. Let's wire it up.&lt;br&gt;
In the &lt;strong&gt;api&lt;/strong&gt; directory(the path: /forum-backend/api/), create the &lt;strong&gt;security&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir security&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the security directory, create the &lt;strong&gt;password.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd security &amp;amp;&amp;amp; touch password.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Token Creation for ResetPassword&lt;/strong&gt; &lt;br&gt;
This is the scenario: when a user requests to change his password, a &lt;strong&gt;token&lt;/strong&gt; is sent to that user's email. A function is written to hash the token. This function will be used when we wire up the &lt;strong&gt;ResetPassword&lt;/strong&gt;  controller file.&lt;br&gt;
Inside the security directory, create the &lt;strong&gt;tokenhash.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch tokenhash.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4:  Seeder&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I think is a good idea to have data to experiment with. We will be seeding the &lt;strong&gt;users&lt;/strong&gt; and &lt;strong&gt;posts&lt;/strong&gt; table when we eventually wire the database.&lt;br&gt;
In the &lt;em&gt;api&lt;/em&gt; directory (in the path: /forum/api/), create a &lt;em&gt;seed&lt;/em&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir seed&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the seed directory, create the seeder file &lt;strong&gt;seeder.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch seeder.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5:  Using JWT for Authentication&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This app will require authentication for several things such as creating a post, liking a post, updating a profile, commenting on a post, and so on. We need to put in place an authentication system. &lt;br&gt;
Inside the &lt;em&gt;api&lt;/em&gt; directory, create the &lt;strong&gt;auth&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir auth&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;auth&lt;/strong&gt; directory, create the &lt;strong&gt;token.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd auth &amp;amp;&amp;amp; touch token.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 6:  Protect App with Middlewares&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We created authentication in &lt;strong&gt;step 5&lt;/strong&gt;. Middlewares are like the Police. They will ensure that the &lt;strong&gt;auth&lt;/strong&gt; rules are not broken.&lt;br&gt;
The &lt;strong&gt;CORS&lt;/strong&gt; middleware will allow us to interact with the &lt;strong&gt;React Client&lt;/strong&gt; that we will be wiring up in &lt;strong&gt;section 2&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;api&lt;/em&gt; directory, create the &lt;strong&gt;middlewares&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir middlewares&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then create the &lt;strong&gt;middlewares.go&lt;/strong&gt; file inside the middlewares directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd middlewares &amp;amp;&amp;amp; touch middlewares.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 7: Utilities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;a. Error Formatting&lt;/strong&gt;&lt;br&gt;
We will like to handle errors nicely when they occur.&lt;br&gt;
The &lt;em&gt;ORM&lt;/em&gt;(Object-Relational Mapping) that is used in the app is &lt;em&gt;GORM&lt;/em&gt;. There are some error messages that are not displayed nicely, especially those that occurred when the database is hit. &lt;br&gt;
For instance, when a user inputs someone else email that is already in our database, in an attempt to sign up, we need to prevent such action and politely tell the user that he can't use that email.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;api&lt;/strong&gt; directory, create a the &lt;strong&gt;utils&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir utils&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;utils&lt;/strong&gt; directory, create a &lt;strong&gt;formaterror&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd utils &amp;amp;&amp;amp; mkdir formaterror&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then create the &lt;strong&gt;formaterror.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd formaterror &amp;amp;&amp;amp; touch formaterror.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. File Formatting&lt;/strong&gt;&lt;br&gt;
A user will need to update his profile(including adding an image) when he does, we will need to make sure that we image added has a unique name.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;utils&lt;/strong&gt; directory(path: /forum-backend/api/utils), create the &lt;strong&gt;fileformat&lt;/strong&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir fileformat&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then create the &lt;strong&gt;fileformat.go&lt;/strong&gt; file inside the &lt;strong&gt;fileformat&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd fileformat &amp;amp;&amp;amp; touch fileformat.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 8: Emails&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Remember when we were wiring up the models, we had the &lt;strong&gt;ResetPassword&lt;/strong&gt; model. Well, when a user wishes to change his password, an email is sent to him with instructions to do so. Let set up that email file.&lt;br&gt;
The emails are handled using &lt;a href="https://sendgrid.com" rel="noopener noreferrer"&gt;Sendgrid&lt;/a&gt; service.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;api&lt;/strong&gt; directory, create a &lt;strong&gt;mailer&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir mailer&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;mailer&lt;/strong&gt; directory create the &lt;strong&gt;forgot_password_mail.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd mailer &amp;amp;&amp;amp; touch forgot_password_mail.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 9: Wiring Up Controllers and Routes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I perceive you might be have been thinking how all these things connect right? Well, perish the thought, because we are finally there.&lt;br&gt;
This step was purposely skipped until now because it calls most of the functions and methods we defined above.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;api&lt;/strong&gt; directory(path: /forum-backend/api/), create the &lt;strong&gt;controllers&lt;/strong&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir controllers&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You might need to pay close attention to this directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. The base file&lt;/strong&gt;&lt;br&gt;
This file will have our database connection information, call our routes, and start our server:&lt;br&gt;
Inside the &lt;strong&gt;controllers&lt;/strong&gt; directory, create the &lt;strong&gt;base.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd controllers &amp;amp;&amp;amp; touch base.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Users Controller&lt;/strong&gt;&lt;br&gt;
Inside the &lt;strong&gt;controllers&lt;/strong&gt; directory, create the &lt;strong&gt;users_controller.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch users_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;From the above file, you can observe that we sent a photo upload to either &lt;a href="https://www.digitalocean.com/products/spaces" rel="noopener noreferrer"&gt;DigitalOceanSpaces&lt;/a&gt; or &lt;a href="https://aws.amazon.com/s3" rel="noopener noreferrer"&gt;AWS S3 Bucket&lt;/a&gt;&lt;br&gt;
If you wish to practice along, You will need to create an Amazon S3 bucket or  DigitalOcean Spaces object to store the images. &lt;br&gt;
Also, update your &lt;strong&gt;.env&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DO_SPACES_KEY=your_do_key
DO_SPACES_SECRET=your_do_secret
DO_SPACES_TOKEN=your_do_token
DO_SPACES_ENDPOINT=your_do_endpoint
DO_SPACES_REGION=your_do_region
DO_SPACES_URL=your_do_url

# OR USING S3:

AWS_KEY=your_aws_key
AWS_SECRET=your_aws_secret
AWS_TOKEN=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;c. Posts Controller&lt;/strong&gt;&lt;br&gt;
Inside the &lt;strong&gt;controllers&lt;/strong&gt; directory, create the &lt;strong&gt;posts_controller.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch posts_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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



&lt;p&gt;&lt;strong&gt;c. Login Controller&lt;/strong&gt;&lt;br&gt;
Request that update a user, create a post, delete a post, and so on, need authentication.&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;controllers&lt;/strong&gt; directory, create the &lt;strong&gt;login_controller.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch login_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. Likes Controller&lt;/strong&gt;&lt;br&gt;
An authenticated user can like a post or unliked already liked post.&lt;br&gt;
Inside the &lt;strong&gt;controllers&lt;/strong&gt; directory, create &lt;strong&gt;likes_controller.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch likes_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. Comments Controller&lt;/strong&gt;&lt;br&gt;
The authenticated user can create/update/delete a comment for a particular post.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch comments_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. ResetPassword Controller&lt;/strong&gt;&lt;br&gt;
A user can request to reset their password peradventure the password is forgotten:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch resetpassword_controller.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;f. Routes&lt;/strong&gt;&lt;br&gt;
All controller methods are used here.&lt;br&gt;
Still, in the &lt;strong&gt;controllers&lt;/strong&gt; directory, create the &lt;strong&gt;routes.go&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch routes.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 10: Create the Server File&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the &lt;strong&gt;server.go&lt;/strong&gt; file, we open a connection to the database, provide a port the app listens to from the &lt;strong&gt;.env&lt;/strong&gt; file.&lt;br&gt;
Inside the &lt;strong&gt;api&lt;/strong&gt; directory(in the path: forum-backend/api/) create the &lt;strong&gt;server.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch server.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 11: Run the App&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's now see some output from our labor thus far.&lt;br&gt;
Create the &lt;strong&gt;main.go&lt;/strong&gt; file in the root directory of the app, and call the &lt;strong&gt;Run&lt;/strong&gt; method defined in &lt;strong&gt;server.go&lt;/strong&gt; file above.&lt;br&gt;
In the path /forum-backend/,&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch main.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;Confirm that your directory structure looks like this:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdm0ju313w38v7xuv8x07.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdm0ju313w38v7xuv8x07.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Running Without Docker&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;If you just want to run this API without docker, make sure you have this in your &lt;strong&gt;.env&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DB_HOST=127.0.0.1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Also that your database is created, the username, password, and every other thing are in place.&lt;/p&gt;

&lt;p&gt;Open the Terminal, in the root directory, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run main.go

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

&lt;/div&gt;


&lt;p&gt;Your terminal output should look like this: &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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgxyl4urdpv53txegk4p2.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgxyl4urdpv53txegk4p2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Running With Docker&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;a. Edit your &lt;strong&gt;.env&lt;/strong&gt; file like this:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DB_HOST=forum-postgres&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;b. Create the Dockerfile for development:&lt;br&gt;
In the project root (path: /forum-backend/), create the &lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Dockerfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You can rename the &lt;strong&gt;example-Dockerfile.dev&lt;/strong&gt;(from the repo)  to &lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;/p&gt;


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



&lt;p&gt;c. Create the docker-compose.yml file for development&lt;br&gt;
In the project root (path: /forum/), create the &lt;strong&gt;docker-compose.yml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch docker-compose.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You can also rename the &lt;strong&gt;example-docker-compose.dev.yml&lt;/strong&gt;  to &lt;strong&gt;docker-compose.yml&lt;/strong&gt;&lt;/p&gt;


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


&lt;p&gt;d. Run the app:&lt;br&gt;
Open the terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up --build

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

&lt;/div&gt;


&lt;p&gt;e. You can use &lt;strong&gt;pgadmin&lt;/strong&gt; to view your database.&lt;br&gt;
 Look up this article I wrote for a guide &lt;a href="https://levelup.gitconnected.com/dockerized-crud-restful-api-with-go-gorm-jwt-postgresql-mysql-and-testing-61d731430bd8" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 13: Writing Unit and Integration Tests&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The API is &lt;strong&gt;99.9%&lt;/strong&gt; tested. &lt;/p&gt;

&lt;p&gt;Golang has a beautiful term called &lt;strong&gt;Table Testing&lt;/strong&gt;.&lt;br&gt;
That term might not sound familiar if you are coming from the NodeJS/PHP/Python/Ruby world.&lt;br&gt;
Table testing in Go, give the Developer the privilege of testing all edge cases of a particular functionality just with one test function.&lt;br&gt;
This is what I mean, Imagine a user signing up. What could possibly go wrong? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user might input an invalid email&lt;/li&gt;
&lt;li&gt;The user might input a password that does not meet the requirement&lt;/li&gt;
&lt;li&gt;The user might input an email that belongs to someone else in our database.

&lt;ul&gt;
&lt;li&gt;and so on.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the power of &lt;strong&gt;Table Tests&lt;/strong&gt;, you can test all the cases with one test function, instead of writing multiple functions with more lines of code to worry about.&lt;/p&gt;
&lt;h4&gt;
  
  
  Tests Set up
&lt;/h4&gt;

&lt;p&gt;Remember, we created a &lt;strong&gt;tests&lt;/strong&gt; directory at the start of the project. &lt;br&gt;
Inside the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;setup_test.go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch setup_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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



&lt;p&gt;Since you will be running this tests in your &lt;strong&gt;local&lt;/strong&gt;, let your &lt;strong&gt;TestMain&lt;/strong&gt; and &lt;strong&gt;Database&lt;/strong&gt; functions look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func TestMain(m *testing.M) {
    var err error
    err = godotenv.Load(os.ExpandEnv("./../.env"))
    if err != nil {
        log.Fatalf("Error getting env %v\n", err)
    }

    Database()

    os.Exit(m.Run())

}

func Database() {

    var err error

    TestDbDriver := os.Getenv("TEST_DB_DRIVER")
    if TestDbDriver == "mysql" {
        DBURL := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&amp;amp;parseTime=True&amp;amp;loc=Local", os.Getenv("TEST_DB_USER"), os.Getenv("TEST_DB_PASSWORD"), os.Getenv("TEST_DB_HOST"), os.Getenv("TEST_DB_PORT"), os.Getenv("TEST_DB_NAME"))
        server.DB, err = gorm.Open(TestDbDriver, DBURL)
        if err != nil {
            fmt.Printf("Cannot connect to %s database\n", TestDbDriver)
            log.Fatal("This is the error:", err)
        } else {
            fmt.Printf("We are connected to the %s database\n", TestDbDriver)
        }
    }
    if TestDbDriver == "postgres" {
        DBURL := fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=disable password=%s", os.Getenv("TEST_DB_HOST"), os.Getenv("TEST_DB_PORT"), os.Getenv("TEST_DB_USER"), os.Getenv("TEST_DB_NAME"), os.Getenv("TEST_DB_PASSWORD"))
        server.DB, err = gorm.Open(TestDbDriver, DBURL)
        if err != nil {
            fmt.Printf("Cannot connect to %s database\n", TestDbDriver)
            log.Fatal("This is the error:", err)
        } else {
            fmt.Printf("We are connected to the %s database\n", TestDbDriver)
        }
    }
}

...

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

&lt;/div&gt;


&lt;p&gt;I had to modify the repository because &lt;strong&gt;Circle CI&lt;/strong&gt; could not detect the &lt;strong&gt;.env&lt;/strong&gt; file that has the test database details. Please take note of this. The rest of the functions in the &lt;strong&gt;setup_test.go&lt;/strong&gt; remain unchanged.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;setup_test.go&lt;/strong&gt; file has functionalities that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializes our testing database&lt;/li&gt;
&lt;li&gt;Refresh the database before each test&lt;/li&gt;
&lt;li&gt;Seed the database with relevant data before each test.
This file is very handy because it will be used throughout the tests. Do well to study it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Model Tests.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;a. User Model Tests&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;model_users_test.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch model_users_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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



&lt;p&gt;After ensuring that your test database is created, the right user and password set and all files saved, You can go ahead and run this test. Launch your terminal in the path: &lt;em&gt;/forum-backend/tests&lt;/em&gt; and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go test -v 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;strong&gt;v flag&lt;/strong&gt; is for verbose output.&lt;br&gt;
To run individual tests in the &lt;strong&gt;model_users_test.go&lt;/strong&gt; file, Say for instance I want to run the &lt;em&gt;TestSaveUser&lt;/em&gt;, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go test -v --run TestSaveUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;b. Post Model Tests&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;model_posts_test.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch model_posts_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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



&lt;p&gt;&lt;strong&gt;c. Like Model Tests&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;model_likes_test.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch model_likes_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. Comment Model Tests&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;model_comments_test.go&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch model_comments_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  Controller Tests.
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;a. Login Controller Test&lt;/strong&gt; &lt;br&gt;
Observe in the &lt;strong&gt;login_controller.go&lt;/strong&gt; file that, the &lt;strong&gt;Login&lt;/strong&gt; method depends on the &lt;strong&gt;SignIn&lt;/strong&gt; method.&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_login_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_login_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Users Controller Test&lt;/strong&gt; &lt;br&gt;
Each method in the users' controller call at least one method from somewhere else. The methods that each Users Controller Method called are tested in the Unit Tests session.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_users_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_users_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. Posts Controller Test&lt;/strong&gt; &lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_posts_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_posts_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. Likes Controller Test&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_likes_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_likes_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. Comments Controller Test&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_comments_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_comments_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;f. ResetPassword Controller Test&lt;/strong&gt;&lt;br&gt;
In the &lt;strong&gt;tests&lt;/strong&gt; directory, create the &lt;strong&gt;controller_reset_password_test.go&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch controller_reset_password_test.go&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;As mentioned earlier, You can run any test in the &lt;strong&gt;tests&lt;/strong&gt; directory. &lt;strong&gt;No test function depends on another to pass.&lt;/strong&gt; All test functions run independently.&lt;/p&gt;

&lt;p&gt;To run the entire test suite use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go test -v 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also run tests from the main directory of the app that is, outside the tests directory(path: /forum-backend/) using:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go test -v ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Running Tests with Docker&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you wish to run the tests with docker, do the following:&lt;/p&gt;

&lt;p&gt;a. Dockerfile.test file&lt;br&gt;
In the root directory, create a &lt;strong&gt;Dockerfile.test&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Dockerfile.test&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You can rename the &lt;strong&gt;example.Dockerfile.test&lt;/strong&gt;(from the repo) to &lt;strong&gt;Dockerfile.test&lt;/strong&gt;&lt;/p&gt;


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



&lt;p&gt;b. docker-compose.test.yml file&lt;br&gt;
In the root directory, create a &lt;strong&gt;docker-compose.test.yml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch docker-compose.test.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You can rename the &lt;strong&gt;example.docker-compose.test.yml&lt;/strong&gt;(from the repo) to &lt;strong&gt;docker-compose.test.yml&lt;/strong&gt;&lt;/p&gt;


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


&lt;p&gt;c. Run the tests suite:&lt;br&gt;
Ensure that the test database details are provided in the &lt;strong&gt;.env&lt;/strong&gt; file and the Test_Host_DB is set as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TEST_DB_HOST=forum-postgres-test 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;From the project root directory, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose -f docker-compose.test.yml up --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 14: Continuous Integration Tools&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Circle CI&lt;/strong&gt; is used as the CI tool in this API.  Another option you might consider is &lt;strong&gt;Travis CI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to Integrate CircleCI:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;a. config.yml&lt;/strong&gt;&lt;br&gt;
In the root directory(path: /forum-backend/), create the &lt;strong&gt;.circleci&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir .circleci&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Create the &lt;strong&gt;config.yml&lt;/strong&gt; file inside the &lt;strong&gt;.circleci&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd .circleci &amp;amp;&amp;amp; touch config.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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



&lt;p&gt;&lt;strong&gt;b. Connect the repository&lt;/strong&gt;&lt;br&gt;
Since you have following this tutorial on your local, you can now create a &lt;strong&gt;github/bitbucket&lt;/strong&gt; repository and push the code.&lt;/p&gt;

&lt;p&gt;Login to &lt;a href="https://circleci.com/vcs-authorize" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt; and choose the repo to build. &lt;br&gt;
Click on start building. &lt;br&gt;
After the build process, you will be notified if it succeeds or fails. For failure, check the logs in the CI environment to know why.&lt;br&gt;
Go to the settings, copy the &lt;strong&gt;badge&lt;/strong&gt; and add it to the &lt;strong&gt;README.md&lt;/strong&gt; of your repo&lt;br&gt;
For a successful build, your badge should look like mine:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcw9vtyuwsewuesxhirzv.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcw9vtyuwsewuesxhirzv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 15: Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I deployed a dockerized version of the app to &lt;a href="https://www.digitalocean.com" rel="noopener noreferrer"&gt;digitalocean&lt;/a&gt;. The job can also be done with &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;Amazon AWS&lt;/a&gt;.&lt;br&gt;
This deployment process is worth a full-blown article. If you be interested in the step by step process, do well to comment, I will spin up a different article for that.&lt;/p&gt;

&lt;p&gt;Get the Repository for the backend &lt;a href="https://github.com/victorsteven/Forum-App-Go-Backend" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Section 2: Buiding the Frontend&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;You might have been waiting for the session.&lt;br&gt;
This is a where you will appreciate the backend work done in &lt;strong&gt;Section 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will be using &lt;strong&gt;React&lt;/strong&gt;. I would have as well decided to use &lt;strong&gt;Vue&lt;/strong&gt;(which is also cool). &lt;br&gt;
&lt;strong&gt;This frontend has zero class definition. React Hooks are used 100%.&lt;/strong&gt;&lt;br&gt;
Redux is used for state management.&lt;/p&gt;

&lt;p&gt;The repository for the frontend is this:&lt;br&gt;
&lt;a href="https://github.com/victorsteven/Forum-App-React-Frontend" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Forum-App-React-Frontend&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Basic Step Up&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;a. Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To follow along from scratch, create a new React Project. Note that this project should be created outside the &lt;strong&gt;backend&lt;/strong&gt;. You can create it in your Desktop, Documents, or your dedicated frontend directory.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-react-app forum-frontend&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Follow the instructions in the terminal after the project is created.&lt;/p&gt;

&lt;p&gt;Change to the &lt;strong&gt;forum-frontend&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd forum-frontend&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;And start the app:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm start&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Visit on the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Please note that I will be as concise as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. Install External Packages&lt;/strong&gt;.&lt;br&gt;
We installed packages like &lt;strong&gt;axios&lt;/strong&gt;, &lt;strong&gt;moment&lt;/strong&gt;, and so on. &lt;br&gt;
To be brief, use the content in the project &lt;strong&gt;package.json&lt;/strong&gt; file:&lt;/p&gt;


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



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm update&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. API Url&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Backend&lt;/strong&gt; is totally standalone from the &lt;strong&gt;Frontend&lt;/strong&gt;&lt;br&gt;
So a means of communication is needed. &lt;br&gt;
Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;apiRoute.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd src &amp;amp;&amp;amp; touch apiRoute.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
Not, from the above file, the &lt;strong&gt;production URL&lt;/strong&gt; for the forum app is used, you can as well change it to yours if you have hosted a backend somewhere.

&lt;p&gt;&lt;strong&gt;d. Authorization&lt;/strong&gt;&lt;br&gt;
Authenticated will be needed for some &lt;strong&gt;requests&lt;/strong&gt; in the app.&lt;br&gt;
Take, for instance, a user needs to be authenticated to &lt;strong&gt;create a post&lt;/strong&gt;.&lt;br&gt;
Since &lt;strong&gt;axios&lt;/strong&gt; is used for &lt;strong&gt;api calls&lt;/strong&gt;(sending requests to the backend), we need to send the authenticated user's &lt;strong&gt;authorization token&lt;/strong&gt; to each request they make. Instead of adding the &lt;strong&gt;authorization token&lt;/strong&gt; manually, let's do it automatically.&lt;br&gt;
Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;authorization&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir authorization&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Create the &lt;strong&gt;authorization.js&lt;/strong&gt; file inside the &lt;strong&gt;authorization&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd authorization &amp;amp;&amp;amp; touch authorization.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. History&lt;/strong&gt;&lt;br&gt;
We may need to call redirection from our redux action. &lt;br&gt;
This is what I mean: When a user creates a post, redirect him to the list of posts available.&lt;br&gt;
To achieve this, we will use the &lt;strong&gt;createBrowserHistory&lt;/strong&gt; function from the history package.&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;history.js&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch history.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;f. Assets&lt;/strong&gt;&lt;br&gt;
For each newly registered user, a default avatar is used as their display image.&lt;br&gt;
Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;assets&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir assets&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Add the &lt;strong&gt;avatar&lt;/strong&gt; below in the &lt;strong&gt;assets&lt;/strong&gt; directory. You can rename it to &lt;strong&gt;Default.png&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq2j8ar9w02cntsu5vhb1.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq2j8ar9w02cntsu5vhb1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Wiring up our Store&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As said earlier, we will be using &lt;strong&gt;redux&lt;/strong&gt; for state management. And I think it is best the store is fired up before we start calling components that we will create later.&lt;br&gt;
Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;store&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd src &amp;amp;&amp;amp; mkdir store&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;store&lt;/strong&gt; directory, create the &lt;strong&gt;modules&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd store &amp;amp;&amp;amp; mkdir modules&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;a. The Authentication Store&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;modules&lt;/strong&gt; directory, create the &lt;strong&gt;auth&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd modules &amp;amp;&amp;amp; mkdir auth&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the auth directory, create these directories and files as shown in the image below:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvsz2lbr3balbh1savejt.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvsz2lbr3balbh1savejt.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i. &lt;strong&gt;auth/actions/authActions.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;ii. &lt;strong&gt;auth/authTypes/index.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;iii. &lt;strong&gt;auth/reducer/authReducer.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  &lt;strong&gt;b. The Posts Store&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;modules&lt;/strong&gt; directory, create the &lt;strong&gt;posts&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir posts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the posts directory, create these directories and files as shown in the image below:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk4ekj40zhe75mdo3lfo8.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk4ekj40zhe75mdo3lfo8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i. &lt;strong&gt;posts/actions/postsActions.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;ii. &lt;strong&gt;posts/postsTypes/index.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;iii. &lt;strong&gt;posts/reducer/postsReducer.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  c. The Likes Store
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;modules&lt;/strong&gt; directory, create the &lt;strong&gt;likes&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir likes&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the likes directory, create these directories and files as shown in the image below:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frixtkae6wm3blwbmre09.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Frixtkae6wm3blwbmre09.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i. &lt;strong&gt;likes/actions/likesActions.js&lt;/strong&gt;&lt;/p&gt;


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


&lt;p&gt;ii. &lt;strong&gt;likes/likeTypes/index.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;iii. &lt;strong&gt;likes/reducer/likesReducer.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  d. The comments Store
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;modules&lt;/strong&gt; directory, create the &lt;strong&gt;comments&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir comments&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Inside the comments directory, create these directories and files as shown in the image below:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8fd1m8r7wfi2w8lcx9yz.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8fd1m8r7wfi2w8lcx9yz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i. &lt;strong&gt;comments/actions/commentsActions.js&lt;/strong&gt;&lt;/p&gt;


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


&lt;p&gt;ii. &lt;strong&gt;comments/commentTypes/index.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;iii. &lt;strong&gt;comments/reducer/commentsReducer.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  e. The Combined Reducer
&lt;/h4&gt;

&lt;p&gt;We will need to combine the reducers from each of the stores defined above.&lt;br&gt;
Inside the &lt;strong&gt;modules&lt;/strong&gt; directory(path: /src/store/modules/), create the &lt;strong&gt;index.js&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  f. The Store File
&lt;/h4&gt;

&lt;p&gt;This is the file that a kind of wraps up the store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;combined reducer&lt;/strong&gt; is called &lt;/li&gt;
&lt;li&gt;We applied the &lt;strong&gt;thunk&lt;/strong&gt; middleware&lt;/li&gt;
&lt;li&gt;Enabled Redux DevTools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;strong&gt;store&lt;/strong&gt; directory(path: /src/store/), create the &lt;strong&gt;index.js&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Wiring Up The Components&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;components&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd src &amp;amp;&amp;amp; mkdir components&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Navigation Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This component takes us wherever we want in the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Navigation&lt;/strong&gt; &lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;Navigation&lt;/strong&gt; component&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd components &amp;amp;&amp;amp; touch Navigation.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Navigation.css&lt;/strong&gt; &lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;Navigation.css&lt;/strong&gt; file&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Utils Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;utils&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir utils&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Message&lt;/strong&gt;: This is the notification component.&lt;br&gt;
Create a &lt;strong&gt;Message.js&lt;/strong&gt; file inside the &lt;strong&gt;utils&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd utils &amp;amp;&amp;amp; touch Message.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Auth Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is the component that will house our authentication.&lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;auth&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir auth&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Signup&lt;/strong&gt;: A user can register on the app.&lt;br&gt;
Create a &lt;strong&gt;Register.js&lt;/strong&gt; file inside the &lt;strong&gt;auth&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd auth &amp;amp;&amp;amp; touch Register.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Login&lt;/strong&gt;: A user can log in.&lt;br&gt;
Create a &lt;strong&gt;Login.js&lt;/strong&gt; file inside the &lt;strong&gt;auth&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Login.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. Auth.css&lt;/strong&gt; Add styling to auth files.&lt;br&gt;
Create a &lt;strong&gt;Auth.css&lt;/strong&gt; file inside the &lt;strong&gt;auth&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Auth.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Users Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The user can update his profile picture, change his email address, request to change his password, and so on.&lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;users&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir users&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Profile&lt;/strong&gt;: A user can update his profile.&lt;br&gt;
Inside the &lt;strong&gt;users&lt;/strong&gt; directory, create the &lt;strong&gt;Profile.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd users &amp;amp;&amp;amp; touch Profile.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Profile.css&lt;/strong&gt;. Add the profile css file.&lt;br&gt;
Inside the &lt;strong&gt;users&lt;/strong&gt; directory, create the &lt;strong&gt;Profile.css&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Profile.css&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. ForgotPassword&lt;/strong&gt;: A user can request to change their forgotten password.&lt;br&gt;
Inside the &lt;strong&gt;users&lt;/strong&gt; directory, create the &lt;strong&gt;ForgotPassword.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch ForgotPassword.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. ResetPassword&lt;/strong&gt;: A user can reset their password. &lt;br&gt;
Inside the &lt;strong&gt;users&lt;/strong&gt; directory, create the &lt;strong&gt;ResetPassword.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch ResetPassword.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Posts Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An authenticated user can create/edit/delete posts they created.&lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;posts&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir posts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Posts&lt;/strong&gt;: A user can view all posts.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;Posts.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd posts &amp;amp;&amp;amp; touch Posts.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Post&lt;/strong&gt;: This a single component inside the &lt;strong&gt;Posts&lt;/strong&gt; component&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;Post.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Post.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. PostDetails&lt;/strong&gt;: A user can visit a particular post.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;PostDetails.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch PostDetails.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. CreatePost&lt;/strong&gt;: An authenticated user can create a post.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;CreatePost.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch CreatePost.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. EditPost&lt;/strong&gt;: An authenticated user can edit their post.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;EditPost.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch EditPost.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;f. DeletePost&lt;/strong&gt;: An authenticated user can delete the post they created.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;DeletePost.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch DeletePost.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;g. AuthPosts&lt;/strong&gt;: An authenticated user view all the posts they created.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;AuthPosts.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch AuthPosts.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;h. AuthPost&lt;/strong&gt;: This is a single component inside the &lt;strong&gt;AuthPosts&lt;/strong&gt; component.&lt;br&gt;
Inside the &lt;strong&gt;posts&lt;/strong&gt; directory, create the &lt;strong&gt;AuthPost.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch AuthPost.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;i. Posts.css&lt;/strong&gt;: This is CSS file for the above components.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  &lt;strong&gt;Likes Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;likes&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir likes&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Likes&lt;/strong&gt;: An authenticated user can like a post or unlike already liked post.&lt;br&gt;
Inside the &lt;strong&gt;likes&lt;/strong&gt; directory, create the &lt;strong&gt;Likes.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd likes &amp;amp;&amp;amp; touch Likes.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Comments Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An authenticated user can create/edit/delete comments they created.&lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;comments&lt;/strong&gt; directory&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir comments&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Comments&lt;/strong&gt;: A user can view all comments for a post.&lt;br&gt;
Inside the &lt;strong&gt;comments&lt;/strong&gt; directory, create the &lt;strong&gt;Comments.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd comments &amp;amp;&amp;amp; touch Comments.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;b. Comment&lt;/strong&gt;: This a single component inside the &lt;strong&gt;Comments&lt;/strong&gt; component.&lt;br&gt;
Inside the &lt;strong&gt;comments&lt;/strong&gt; directory, create the &lt;strong&gt;Comment.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Comment.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;c. CreateComment&lt;/strong&gt;: An authenticated user can create a comment.&lt;br&gt;
Inside the &lt;strong&gt;comments&lt;/strong&gt; directory, create the &lt;strong&gt;CreateComment.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch CreateComment.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;d. EditComment&lt;/strong&gt;: An authenticated user can edit their comment.&lt;br&gt;
Inside the &lt;strong&gt;comments&lt;/strong&gt; directory, create the &lt;strong&gt;EditComment.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch EditComment.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;p&gt;&lt;strong&gt;e. DeleteComment&lt;/strong&gt;: An authenticated user can delete their comment.&lt;br&gt;
Inside the &lt;strong&gt;comments&lt;/strong&gt; directory, create the &lt;strong&gt;DeleteComment.js&lt;/strong&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch DeleteComment.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h4&gt;
  
  
  &lt;strong&gt;Dashboard Component&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is the entry component of the application.&lt;br&gt;
Inside the &lt;strong&gt;components&lt;/strong&gt; directory, create the &lt;strong&gt;Dashboard.js&lt;/strong&gt; component&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Dashboard&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Wiring Up The Route&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If routing is not in place, we cannot navigate to the different components we have.&lt;br&gt;
In the &lt;strong&gt;src&lt;/strong&gt; directory, create the &lt;strong&gt;Route.js&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch Route.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


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


&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Wiring Up The App Main Entry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;All that is done above, from the &lt;em&gt;store&lt;/em&gt;* to the &lt;strong&gt;routing&lt;/strong&gt; need to connect at some point. &lt;br&gt;
This is done in the &lt;strong&gt;index.js&lt;/strong&gt; file in the &lt;strong&gt;src&lt;/strong&gt; directory.&lt;/p&gt;

&lt;p&gt;Edit the &lt;strong&gt;index.js&lt;/strong&gt; file in the &lt;strong&gt;src&lt;/strong&gt; directory &lt;/p&gt;


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


&lt;p&gt;Also, edit the &lt;strong&gt;index.css&lt;/strong&gt; file in the &lt;strong&gt;src&lt;/strong&gt; directory. This file has just once CSS class &lt;strong&gt;color-red&lt;/strong&gt;. This is used in all components that error is displayed&lt;/p&gt;


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


&lt;p&gt;Fire up your terminal and run &lt;strong&gt;&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the App.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The frontend is deployed using &lt;a href="https://www.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;&lt;br&gt;
before you deploy, in the &lt;strong&gt;public&lt;/strong&gt; directory(path: forum-frontend/public), create the &lt;strong&gt;_redirects&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch _redirects&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;File content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/*    /index.html   200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Steps to deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new github repo(different from the backend)&lt;/li&gt;
&lt;li&gt;Push the frontend code to the repo&lt;/li&gt;
&lt;li&gt;Login to your &lt;strong&gt;Netlify&lt;/strong&gt; account and connect the frontend repo.&lt;/li&gt;
&lt;li&gt;Give it sometime to deploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note the following:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the backend to work with the deployed frontend, it needs to be deployed also to a live server(digitalocean, aws, heroku, etc).&lt;/li&gt;
&lt;li&gt;Make sure that url for the backend is not just the &lt;strong&gt;ip&lt;/strong&gt; address. you can get a domain name and make sure &lt;strong&gt;https&lt;/strong&gt; is enabled&lt;/li&gt;
&lt;li&gt;You can update the &lt;strong&gt;apiRoute&lt;/strong&gt; file and add your backend url &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I tried as concise as possible to avoid a &lt;strong&gt;2 hours&lt;/strong&gt; or so read.&lt;/p&gt;

&lt;p&gt;This is the visit the production application&lt;br&gt;
&lt;a href="https://seamflow.com" rel="noopener noreferrer"&gt;https://seamflow.com&lt;/a&gt; &lt;br&gt;
You can visit and try all that you learned in this article.&lt;/p&gt;

&lt;p&gt;Also, get the github repositories&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/victorsteven/Forum-App-Go-Backend" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Forum-App-Go-Backend&lt;/a&gt; (Backend)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/victorsteven/Forum-App-React-Frontend" rel="noopener noreferrer"&gt;https://github.com/victorsteven/Forum-App-React-Frontend&lt;/a&gt; (Frontend)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't forget to drop a star.&lt;/p&gt;

&lt;p&gt;You can ask me personal questions on questions on &lt;a href="https://twitter.com/stevensunflash" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might also like to check out my other articles about &lt;strong&gt;go&lt;/strong&gt;, &lt;strong&gt;docker&lt;/strong&gt;, &lt;strong&gt;kubernetes&lt;/strong&gt; &lt;a href="https://medium.com/@victorsteven" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks.&lt;/p&gt;

</description>
      <category>go</category>
      <category>gin</category>
      <category>react</category>
      <category>redux</category>
    </item>
  </channel>
</rss>
