<?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: David Losert</title>
    <description>The latest articles on DEV Community by David Losert (@davelosert).</description>
    <link>https://dev.to/davelosert</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%2F188363%2Fa856eda6-cdbf-477e-a9ad-8dfc6b5b9437.jpeg</url>
      <title>DEV Community: David Losert</title>
      <link>https://dev.to/davelosert</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davelosert"/>
    <language>en</language>
    <item>
      <title>Mock-Factory-Pattern in TypeScript</title>
      <dc:creator>David Losert</dc:creator>
      <pubDate>Mon, 12 Jul 2021 14:24:40 +0000</pubDate>
      <link>https://dev.to/davelosert/mock-factory-pattern-in-typescript-44l9</link>
      <guid>https://dev.to/davelosert/mock-factory-pattern-in-typescript-44l9</guid>
      <description>&lt;p&gt;If you are writing automated tests (and I sure hope you do), you most likely also create a lot of mock-data to feed into the functions under test. With this post I want to show you how to do this in a scalabe, reusable and focused way by using a mock-factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The initial simple way
&lt;/h2&gt;

&lt;p&gt;When starting a new project or test-suite, creating mock-data usually starts out very simple by using object literals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&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;markTodoAsDone sets done to true.&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;const&lt;/span&gt; &lt;span class="na"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write an awesome post about Testdata-Patterns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;done&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultingTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;markTodoAsDone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepStrictEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultingTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&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="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, as your project grows, your data usually grows as well. New properties and behaviours are added, and you will quickly realize that the method above does not scale well. Everytime a new property is introduced, you have to revisit every single test and adjust the testdata-object. Depending on the size of your project, that might be a dozen or even hundreds of required adjustments because of a single change.&lt;/p&gt;

&lt;p&gt;But the example above actually has another issue - can you spot it?&lt;/p&gt;

&lt;p&gt;Maybe it becomes clearer once we actually add some new properties:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&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;markTodoAsDone sets done to true.&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;const&lt;/span&gt; &lt;span class="na"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Write an awesome post about Testdata-Patterns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;done&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="na"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-04&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;David Losert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Writing Blogposts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;writing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&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;resultingTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;markTodoAsDone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepStrictEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultingTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Right, with pure object literals you actually have to specifiy all the properties of the object all the time - even if only one of those is relevant for the unit under test. That is a lot of distraction. Tests should be precise, focused and only contain the data and properties currently required.&lt;/p&gt;
&lt;h2&gt;
  
  
  Alternative ways
&lt;/h2&gt;

&lt;p&gt;So what is the alternative, you might ask? I have seen quite some, but they usually only address parts of the problem or introduce new ones:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Putting test-objects into their own files&lt;/strong&gt; This might remove the distraction - but it also removes the property the test is about. Also, it does not help you with the sclaing issue - on the contrary. Creating a file for every test or maybe different test scenarios, you now have to go into every file whenever something on the source type is changed. And it becomes quite a mess pretty fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Casting with TypeScript's &lt;code&gt;as&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unfinishedTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;done&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="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;While this most certainly works, it leaves a bit of a bad taste as it is actually cheating the type system, thus openning the door to nasty and hard to track bugs. If the function under test expects a &lt;code&gt;Todo&lt;/code&gt;, we should provide a full-fledged object and not just a partial one. Maybe the unit under test relies on a ceratin property not being undefined even though it's not really relevant for the test (thinking of a 'stub'). Plus you have to type &lt;code&gt;as Thing&lt;/code&gt; everywhere which again is quite a bit of a distraction in my eyes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spreading on a default object&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// In a separe file or on top of your test file...&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Default Todo Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;done&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="na"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-04&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;David Losert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Writing Blogposts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;writing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&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="nf"&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;markTodoAsDone sets done to true.&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;const&lt;/span&gt; &lt;span class="na"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&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="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;done&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This heads into a better direction. The test remains focused on the relevant properties, yet our unit under test always gets a real &lt;code&gt;Todo&lt;/code&gt;-object as opposed to when casting. It also scales somewhat: changes to the type only have to be applied to the &lt;code&gt;defaultTodo&lt;/code&gt;-object. And we get another bonus: the &lt;code&gt;defaultTodo&lt;/code&gt; serves as a great documentation on how a real &lt;code&gt;Todo&lt;/code&gt;-object might look in production.&lt;/p&gt;

&lt;p&gt;There remains a tiny problem with this approach: Your tests are now tightly coupled to the &lt;code&gt;defaultTodo&lt;/code&gt;-object, which might again introduce problems with - you might have guessed it - scaling. And I wouldn't write this if I did not know of a slightly better approach.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Enter the stage: TypeScripts &lt;code&gt;Partial&lt;/code&gt; and a factory-function
&lt;/h2&gt;

&lt;p&gt;So the way I usually go is a combination of TypeScript's &lt;code&gt;Partial&lt;/code&gt; and a simple factory function. I'll show you the code before going into the details.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;createMockTodo.ts&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Default Todo Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;done&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="na"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-04&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;David Losert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Writing Blogposts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;writing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&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;createMockTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createMockTodo&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The usage of might look like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;todo.test.ts&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&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;markTodoAsDone sets done to true.&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;const&lt;/span&gt; &lt;span class="na"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockTodo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;done&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultingTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;markTodoAsDone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unfinishedTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepStrictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultingTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So there is a few things happening here, let me walk you through the most important ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;defaultTodo&lt;/code&gt; is basically the same as in the section before: A fully defined object of the type to make it easy to always get all (required) properties from a single place. Additional advantage: It serves as documentation about the type.&lt;/li&gt;
&lt;li&gt;But rather than exporting this object directly, we use a factory function &lt;code&gt;createMockTodo&lt;/code&gt;. This gives us way more control over how the actual mock-object is constructed. You will see how this helps us further down.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Partial&amp;lt;T&amp;gt;&lt;/code&gt; is a TypeScript utility type that accepts another &lt;code&gt;Type&lt;/code&gt; or &lt;code&gt;Interface&lt;/code&gt; as generic argument (if you don't know about generics, I recommend you read the &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;). It then creates a new type by copying all properties of the given generic input type but with all properties set to optional.&lt;/p&gt;

&lt;p&gt;This lets us pass in a object with only the properties of our choosing (as we did with &lt;code&gt;done&lt;/code&gt; in the example) while at the same time keeping type-safety turned on. We can only pass things that actually exist in &lt;code&gt;Todo&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We use an empty object as deafult argument to &lt;code&gt;overwrites&lt;/code&gt; so that we can also call the factory-function without any parameters. This is especially useful if you just need some stubs in your test but don't care about the precise properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We then finally construct the test-object by merging together all properties of &lt;code&gt;defaultTodo&lt;/code&gt; with the &lt;code&gt;overwrite&lt;/code&gt; object using the spread-operators.&lt;/p&gt;

&lt;p&gt;Like this, all properties given to the function will overwrite the ones in &lt;code&gt;defaultTodo&lt;/code&gt; (as the name indicates) while leaving the other properties in place.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Advantages of this pattern
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It scales&lt;/strong&gt;: when adding new properties to the original type, you only have to adjust the default-Object in a single place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It scales again&lt;/strong&gt;: If for any reason you need to construct the mock-data differently (e.g. because of deeply nested structures, see below), you are completely free to do so within the factory-function without having to change any callers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safety&lt;/strong&gt; is on at all times. This prevents you from introdcuing nasty bugs, as well as making refactorings easy, especially with IDEs that support things like renamings (Hit &lt;code&gt;F2&lt;/code&gt; in VSCode ;) ).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's immutable&lt;/strong&gt;: As long as you don't have nested objects (again, see below on how to handle those), you are guaranteed to get a new copy for every test, preventing another sort of nasty bugs where tests might influence each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's documentation&lt;/strong&gt;: You can give the default-object meaningful values to have a documentation on how it might look like in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's reusable&lt;/strong&gt;: This pattern can be used in a lot of different scenarios - it is actually not even limited to data-objects as you might find out if you read on.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Extending the pattern
&lt;/h2&gt;

&lt;p&gt;The pattern as shown is already useful in a lot of ways. But I promised you scaling, so let me show you how to further extend it for more special use-cases.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use mock-factories in other mock-factories
&lt;/h3&gt;

&lt;p&gt;Lets say we introduce a &lt;code&gt;User&lt;/code&gt;-Type in our App that might look like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;User.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;pronouns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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 create a mock-factory for it:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;createMockUser.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultUser&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;29f51e42-c6ca-4f17-ac93-7131eeb4cffc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Kim&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Su&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pronouns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;they/them&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;createMockUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we want to adjust our &lt;code&gt;Todo.assignee&lt;/code&gt;-Property to use this type rather than a string:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Todo.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;assignee&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="nl"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;This will break all our tests at first, so we quickly adjust the default-object in the &lt;code&gt;Todo&lt;/code&gt;-Factory:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;createMockTodo.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createMockUser&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;./createMockUser&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;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Default Todo Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;done&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="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createMockUser&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;dueDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-07-04&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Writing Blogposts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;writing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&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;createMockTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createMockTodo&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And that's it. Our tests should work again, given they did not involve or overwrite the user object. And if they did, we can now easily find them through our typechecks (or by following the failed tests for that matter).&lt;/p&gt;

&lt;p&gt;For example imagine we had a test like this before the change:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Todo.test.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&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;changes the assignee to the new given 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;givenTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockTodo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;David Losert&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="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;actualUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;assignTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;givenTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rahim Vera&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepStrictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actualUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rahim Vera&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;Now we could write it like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&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;changes the assignee to the new given 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;givenTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockTodo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createMockUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oldId&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;expectedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;newId&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="na"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;actualUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;assignTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;givenTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expectedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deepStrictEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actualUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expectedUser&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 to be careful though: Now that we use nested objects, we are actually able to mutate the values within the &lt;code&gt;defaultTodo&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFirstTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockTodo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myFirstTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Logs 'Kim'&lt;/span&gt;

&lt;span class="nx"&gt;myFirstTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MutatedName&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;mySecondTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMockTodo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mySecondTodo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assignee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Now Logs 'MutatedName'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is due to the fact that the spread-operator only does a shallow copy of an object, but passes deep nested objects by reference.&lt;/p&gt;

&lt;p&gt;This is not too bad if we are actually certain that we are using immutabilty throughout our app. But if not, there is the option of deep cloning.&lt;/p&gt;
&lt;h3&gt;
  
  
  Use &lt;code&gt;cloneDeep&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;As there actually is no standard way of deep cloning an object in JavaScript / TypeScript, we'll either have to implement it ourselfs or use a library that does it for us. For the simplicity of this post, I will be using the &lt;code&gt;cloneDeep&lt;/code&gt;-function provided by &lt;a href="https://www.npmjs.com/package/lodash" rel="noopener noreferrer"&gt;lodash&lt;/a&gt;, since it is probably the most popular one.&lt;/p&gt;

&lt;p&gt;If we do not want the full lodash-library in our project, we can also do a standalone install of the &lt;code&gt;cloneDeep&lt;/code&gt; function and mark it as a dev-dependency (so long as we only use it in our tests):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; lodash.clonedeep @types/lodash.clonedeep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Please note that you will have to add &lt;code&gt;"esModuleInterop": true&lt;/code&gt; in the &lt;code&gt;compilerOptions&lt;/code&gt;-section of your &lt;code&gt;tsconfig.json&lt;/code&gt; to be able use it.&lt;/p&gt;

&lt;p&gt;Now all that is left todo (pun intended) is to adjust the mock-factory accordingly:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;createMockTodo.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cloneDeep&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;lodash.clonedeep&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createMockTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overwrites&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overwrites&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;And that's it. Now you have a truly immutable mock-factory. Note how we did not have to adjust any tests or other areas of the code to make this central change.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sum up
&lt;/h2&gt;

&lt;p&gt;As shown, the mock-factory-pattern is a big win in scalibility and focus for creating test-data while at the same time being pretty simple. The simplicity makes it reusable for almost every object, and I even use it sometimes to mock IO-Modules like HTTP-Services.&lt;/p&gt;

&lt;p&gt;Using the same pattern for all test-data makes writing tests more approchable, and it is especially helpful for newcomers to the project as they can see default implementations of all the relevant data and types.&lt;/p&gt;

&lt;p&gt;By having a mix of a default-object and a factory-function, it becomes super flexible while at the same time minimizing maintenance tasks and the need for more static mock code. To put this into perspective: I once was able to delete ten thousands of lines of code from a project simply by introducing this pattern.&lt;/p&gt;

&lt;p&gt;And there are still a lot of other ways to use and extend it, but I'll leave it up to you to find and use them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Link to working example
&lt;/h2&gt;

&lt;p&gt;You can find a working example of the code in my Github repository:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davelosert" rel="noopener noreferrer"&gt;
        davelosert
      &lt;/a&gt; / &lt;a href="https://github.com/davelosert/mock-factory-pattern" rel="noopener noreferrer"&gt;
        mock-factory-pattern
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This repository shows the mock-factory-pattern and accompanies my blog-post about it.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mock-Factory-Pattern in TypeScript&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;This repository shows a mock-factory-pattern-example in typescript.&lt;/p&gt;

&lt;p&gt;The mock-factory-pattern uses a combination of TypeScript's &lt;code&gt;Partial&lt;/code&gt; together with a factory function to be able to create scalabe, reusable and focused test data:&lt;/p&gt;

&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;defaultObject&lt;/span&gt;: &lt;span class="pl-smi"&gt;ExampleType&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;key1&lt;/span&gt;: &lt;span class="pl-s"&gt;'value1'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;key2&lt;/span&gt;: &lt;span class="pl-s"&gt;'value2'&lt;/span&gt;
  &lt;span class="pl-c"&gt;// ...&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;createMockObject&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;overwrites&lt;/span&gt;: &lt;span class="pl-smi"&gt;Partial&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-smi"&gt;ExampleType&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  ...&lt;span class="pl-s1"&gt;defaultObject&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  ...&lt;span class="pl-s1"&gt;overwrites&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-s1"&gt;createMockObject&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can find two implementations of this pattern here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/davelosert/mock-factory-pattern./src/createMockUser.ts" rel="noopener noreferrer"&gt;src/createMockUser.ts&lt;/a&gt;: simple example&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/davelosert/mock-factory-pattern./src/createMockTodo.ts" rel="noopener noreferrer"&gt;src/createMockTodo.ts&lt;/a&gt;: example using &lt;code&gt;cloneDeep&lt;/code&gt; to ensure immutability.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can read more about it in my &lt;a href="https://dev.to/davelosert/mock-factory-pattern-in-typescript-44l9" rel="nofollow"&gt;blog-post&lt;/a&gt; which this repository accompanies.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;To execute the tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone this repository and &lt;code&gt;cd&lt;/code&gt; into it on your terminal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm test&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/davelosert/mock-factory-pattern" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>typescript</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Practical guide to use  the Microsoft Graph-API</title>
      <dc:creator>David Losert</dc:creator>
      <pubDate>Tue, 06 Apr 2021 15:38:45 +0000</pubDate>
      <link>https://dev.to/davelosert/practical-guide-to-use-the-microsoft-graph-api-4ahn</link>
      <guid>https://dev.to/davelosert/practical-guide-to-use-the-microsoft-graph-api-4ahn</guid>
      <description>&lt;p&gt;The Microsoft Graph-API is the gateway to almost all data living within a Microsoft365 subscription, and is therefore a super powerful API for a lot of different use cases.&lt;/p&gt;

&lt;p&gt;But approaching and using it for the first time can be very difficult and overwhelming – especially because the &lt;a href="https://docs.microsoft.com/en-us/graph/overview" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; is very complex and information is shattered across a lot of different pages.&lt;/p&gt;

&lt;p&gt;I just had to create a serverless function in Node.js that retrieves some data from a SharePoint-List – and while trying to find out how to do that, I got lost clicking from page to page, concept to concept and code example to code example to find a quick and easy solution I can built upon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal of this post: A pracitcal guide
&lt;/h2&gt;

&lt;p&gt;The main problem I had was: &lt;strong&gt;How to correctly authenticate and authorize my backend-app with a simple secret to use the Graph-API to query general (non-user related) data?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With this post I want to save you the trouble I went through and show you exactly this in a &lt;strong&gt;practical guide&lt;/strong&gt;. I will only explain enough theory for you to understand what is going on.&lt;/p&gt;

&lt;p&gt;The guide explains how to set everything up to query the &lt;strong&gt;SharePoint root site&lt;/strong&gt; as an example, but it also explains how to adjust everything to match your desired data.&lt;/p&gt;

&lt;p&gt;The code examples are written in &lt;strong&gt;TypeScript&lt;/strong&gt; and run in &lt;strong&gt;Node.js&lt;/strong&gt;. But as we will be using the official Azure auth library &lt;a href="https://www.npmjs.com/package/@azure/msal-node" rel="noopener noreferrer"&gt;@azure/msal-node&lt;/a&gt; which is available in other languages as well (you can find a list &lt;a href="https://docs.microsoft.com/en-us/graph/auth/" rel="noopener noreferrer"&gt;here&lt;/a&gt;), the concepts should still be applicable if you fancy another language.&lt;/p&gt;

&lt;p&gt;I am also planning to write a &lt;strong&gt;second part&lt;/strong&gt; to this post that takes a deeper dive into the concepts behind the authentication and authorization models of Microsoft365 and that will explain some leftover questions from this first part – so stay tuned.&lt;/p&gt;

&lt;p&gt;But for now, let's get started.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites – What you need to know first
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Azure AD Application required
&lt;/h2&gt;

&lt;p&gt;In order to authenticate with the Graph-API, you must register an app in the &lt;strong&gt;Azure Active Directory&lt;/strong&gt; (Azure AD for short). This is the way of creating a technical user for the API, and there really is no way around this.&lt;/p&gt;

&lt;p&gt;In hindsight, this was one of the changes in my mental model I had to go through to understand the auth-mechanism of Microsoft365: Rather than creating &lt;strong&gt;a (somewhat anonymous) technical user&lt;/strong&gt; to use the API, you actually &lt;strong&gt;register the app itself&lt;/strong&gt; as identity within your account.&lt;/p&gt;

&lt;p&gt;For the use-case of this post, there is no real technical difference between the two. However, Microsoft allows for far more complex authentication scenarios where this becomes very relevant. I'll talk about those in the second part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Administrator Privileges required
&lt;/h2&gt;

&lt;p&gt;You will need administrator privileges to register the app. If you don't have them, there are three other options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You ask your IT-Department or whoever is in charge to register the app for you.&lt;/li&gt;
&lt;li&gt;You use the &lt;a href="https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade" rel="noopener noreferrer"&gt;App registrations page&lt;/a&gt; in Azure if you have access. This is the admin-free version of registering an app and you can then follow all of the steps below – however, you won't be able to give the consent required in step 1.3. and then still need an administrator to consent for you.&lt;/li&gt;
&lt;li&gt;You create a &lt;strong&gt;completely free&lt;/strong&gt; &lt;a href="https://developer.microsoft.com/en-us/microsoft-365/dev-program" rel="noopener noreferrer"&gt;Microsoft365 Developer test account here&lt;/a&gt; – which gives you a full Microsoft365 E5 Subscription for a renewable 90 days. This is perfect as a playground and what I did to test the code of this post.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Practical Guide
&lt;/h1&gt;

&lt;p&gt;Now lets dive into the practical part which consists of three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Registering an Azure AD Application&lt;/li&gt;
&lt;li&gt;2. Using TypeScript to query the API&lt;/li&gt;
&lt;li&gt;3. Using the Graph-Explorer to find the right query&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Registering an Azure AD Application
&lt;/h2&gt;

&lt;p&gt;If you have administrator privileges, you can reach the Azure AD App registrations page by opening your browser and navigating to &lt;a href="https://aad.portal.azure.com" rel="noopener noreferrer"&gt;https://aad.portal.azure.com&lt;/a&gt;. This should bring you to the Azure Active Directory admin center of your Microsoft365 or Azure Subscription  once you logged in with your administrator account.&lt;/p&gt;

&lt;p&gt;Alternatively, you can reach it from either within your &lt;a href="https://admin.microsoft.com/#/homepage" rel="noopener noreferrer"&gt;Microsoft365 admin center&lt;/a&gt; in the navigation on the left, or from the &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;Azure portal&lt;/a&gt; by searching for it in the top bar.&lt;/p&gt;

&lt;p&gt;Whatever way you chose, once you are there, on the left side click &lt;strong&gt;Azure Active Directory&lt;/strong&gt; and then &lt;strong&gt;App registrations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg18nopjv0hr686uvq5wo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg18nopjv0hr686uvq5wo.png" alt="Screenshot of the Azure AD admin center with red circles on Azure Active Directory Link and App registrations and an arrow linking both circles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we'll have to do 3 things: &lt;strong&gt;register the app&lt;/strong&gt;, then &lt;strong&gt;create a client secret&lt;/strong&gt; and in the end &lt;strong&gt;add some permissions&lt;/strong&gt; to it – which I'll explain step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't worry of making any mistakes here – you can always adjust the settings later and there is absolutely no risk of creating any costs as registering an app is completely free&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1. Registering the Application
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;New Registration&lt;/strong&gt; on the top bar.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t0ngs511ixzmon1uz0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t0ngs511ixzmon1uz0x.png" alt="Screenshot of the App registration page with a circle on the new registration button"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill the Form with a &lt;strong&gt;name&lt;/strong&gt; of your choosing and select "&lt;strong&gt;Accounts in this organizational directory only&lt;/strong&gt;" (you can omit the Redirect URI), then hit &lt;code&gt;Register&lt;/code&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc8stzgezox39n67s8el.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc8stzgezox39n67s8el.png" alt="Screenshot of the app registration form, the name field is MyTestApplication and the radio button selects Accounts in this organizational directory only"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see a summary screen of your app from which you will later need the values of the &lt;strong&gt;Application (client) id&lt;/strong&gt; and the &lt;strong&gt;Directory (tenant) id&lt;/strong&gt;. You can copy and store them now or retrieve them again later.&lt;/p&gt;

&lt;p&gt;Think of those variables like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;tenant-id&lt;/strong&gt;: The unique Id of the entire Microsoft365- or Azure-Account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;client-id&lt;/strong&gt;: The username of the technical user our application will use to authenticate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now all that is missing for a proper &lt;strong&gt;authentication&lt;/strong&gt; is a password or &lt;code&gt;client-secret&lt;/code&gt; – we will create this in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2. Authentication: Create a client-secret
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;On the left, select &lt;code&gt;Certificates &amp;amp; secrets&lt;/code&gt; and click &lt;code&gt;New Client secret&lt;/code&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ueivczrzozc3y22d3kf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ueivczrzozc3y22d3kf.png" alt="Screenshot of the App registration page with red circles around Certificate &amp;amp; secrets and New client secret and an arrow connecting both"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give it any name and choose an expiry date (you can just use &lt;code&gt;Never&lt;/code&gt; for now).&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhnkwat1015mt6dm028y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhnkwat1015mt6dm028y.png" alt="Screenshot of the Add a client secret form with the Description input set to TestSecret and the Expires radiobutton selecting Never"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should see the created secret and the value in clear text. &lt;strong&gt;Copy and store this value somewhere now – this will be the only time you can see it.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faylac2vwj5xwnqo6r6lm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faylac2vwj5xwnqo6r6lm.png" alt="105_Store_Value"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One note: Don't confuse the &lt;code&gt;ID&lt;/code&gt; field of this screen with the &lt;strong&gt;client-id&lt;/strong&gt; of the previous step – they are not the same and you won't need the &lt;strong&gt;client-secret-id&lt;/strong&gt; from here anymore.&lt;/p&gt;

&lt;p&gt;Now we have everything we need to let our application &lt;strong&gt;authenticate&lt;/strong&gt; against Azure AD. However, we didn't tell Azure-AD what data our application is allowed or &lt;strong&gt;authorized&lt;/strong&gt; to retrieve yet, so lets do this next.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.3. Authorization: Grant permissions to your app
&lt;/h3&gt;

&lt;p&gt;Still on the Azure AD Application page:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;API Permissions&lt;/strong&gt; and hit &lt;strong&gt;Add Permissions&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmu0atwak5roy5oljr3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxmu0atwak5roy5oljr3x.png" alt="Screenshot of the app registration page with red circles on the API permissions navigation and the add permissions button and an arrow connecting the two"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Graph API&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0balmq2dvgvrtrme44s3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0balmq2dvgvrtrme44s3.png" alt="Screenshot of the  Request API permissions form showing the selection of the microsoft graph api"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Application permissions&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgryf1nunpm63w7plu6ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgryf1nunpm63w7plu6ga.png" alt="Screenshot of the Request API permissions form with a red circle around the Application permissions button"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search and select &lt;strong&gt;Sites.ReadAll&lt;/strong&gt;. This is the permission that allows us to read all SharePoint-Data. If you need to query other data and therefore need other permissions, you can later use the Graph-Explorer as explained in Step 3.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnq5048b10mozq58b9pw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnq5048b10mozq58b9pw.png" alt="Screenshot of the Requst API permissions form where the search input is Sites and the selected permission is Sites.Read.All"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Add Permissions&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Back on the permissions-screen, click &lt;strong&gt;Grant admin consent&lt;/strong&gt; to actually allow those permissions. I'll explain in the second part why this is necessary, for now just do it.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxckddurxf8jaw27ambwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxckddurxf8jaw27ambwa.png" alt="Screenshot of the API permissions overview with a circle on the grant admin consent button"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And that's it. Now we are ready to write some code to use the Graph-API and retrieve SharePoint-Data from our Microsoft365 account.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Using TypeScript to query the API
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1. Install the necessary libraries
&lt;/h3&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @azure/msal-node node-fetch


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

&lt;/div&gt;

&lt;p&gt;MSAL stands for &lt;em&gt;Microsoft Authentication Library&lt;/em&gt; and&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/@azure/msal-node" rel="noopener noreferrer"&gt;@azure/msal-node&lt;/a&gt; is the official library to authenticate with Azure AD from a Node.js Application. It kind of suffers from the same bloated and confusing documentation as the Graph-API, so finding the right classes and functions to use can be very cumbersome. However, we will see in the code below that we really only need a few lines to make it work.&lt;/p&gt;

&lt;p&gt;We are also installing &lt;a href="https://www.npmjs.com/package/node-fetch" rel="noopener noreferrer"&gt;node-fetch&lt;/a&gt; as the Graph-API is an http-endpoint – but you can use any other http-library you fancy.&lt;/p&gt;

&lt;p&gt;If you found the official client &lt;a href="https://www.npmjs.com/package/@microsoft/microsoft-graph-client" rel="noopener noreferrer"&gt;@microsoft/microsoft-graph-client&lt;/a&gt; on npm – do not use it. At least according to their documentation, it is not compatible with the simple credential-authentication that we are trying to use here.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2. Create a file &lt;code&gt;queryGraphAPI.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Have a look at the full code-example first and explain the details after:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;msal&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;@azure/msal-node&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="nx"&gt;fetch&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;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tenantId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;YOUR_TENANT_ID&amp;gt;&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;clientId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;YOUR_APPLICATION_ID&amp;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;// 2.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;YOUR_CLIENT_SECRET&amp;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;// const clientSecret = process.env.CLIENT_SECRET&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// 3.&lt;/span&gt;
    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://login.microsoftonline.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;// 4.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authClient&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;msal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ConfidentialClientApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientConfig&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;queryGraphApi&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="nx"&gt;path&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="c1"&gt;// 5.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokens&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;authClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;acquireTokenByClientCredential&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// 6.&lt;/span&gt;
    &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://graph.microsoft.com/.default&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;rawResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://graph.microsoft.com/v1.0&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 7.&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;rawResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;queryGraphApi&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;



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

&lt;/div&gt;
&lt;h4&gt;
  
  
  How this code works
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You will recognize the &lt;strong&gt;tenantId&lt;/strong&gt;, &lt;strong&gt;clientId&lt;/strong&gt; from step 1.1. – fill them in here directly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;clientSecret&lt;/strong&gt; from step 1.2. is &lt;strong&gt;sensitive information&lt;/strong&gt;, so you should not be using it in your code and &lt;strong&gt;never commit it to your repo&lt;/strong&gt;. For a quick test it's okay, later on you better provide this value through an environment variable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The authority is the endpoint that the msal-library will authenticate with. Maybe now it is clear why you need the unique &lt;strong&gt;tenantId&lt;/strong&gt; – it let's the generic login-endpoint of microsoft know for which account your are trying to authenticate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are using the &lt;code&gt;ConfidentialClientApplicaton&lt;/code&gt;-Class of &lt;code&gt;msal&lt;/code&gt;. It is named confidential as our application is running completely in the backend where the &lt;code&gt;clientSecret&lt;/code&gt; is safe. There is a differentiation to &lt;code&gt;public&lt;/code&gt; clients as the &lt;code&gt;msal&lt;/code&gt; library also offers authentication mechanisms for browser-based applications where using a general secret would not be secure (everyone could read and use it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As you might see, we do not query the Graph-API with our credentials directly, but we only use them to get an &lt;strong&gt;access-token&lt;/strong&gt;. If you are familiar with the OAuth2 and OpenID stack, you might recognize this pattern. If not don't worry, I'll talk more about it in the second part.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With the &lt;strong&gt;scope&lt;/strong&gt;, we tell the auth-endpoint that we want the token to be allowed to access the Graph-API with the &lt;code&gt;.default&lt;/code&gt;-permissions – which are the ones we configured already in Step  1.2. For our use-case, this is the only possible option, but again there are other use-cases where setting other values here makes sense (which – you guessed it – will be covered in the second part).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we query the Graph-API endpoint with the retrieved token. The &lt;code&gt;path&lt;/code&gt; Parameter defines which data to query, and in 2.3. we will use it with &lt;code&gt;/sites/root&lt;/code&gt; which is the SharePoint Endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  2.3. Use the API in an &lt;code&gt;index.ts&lt;/code&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;queryGraphApi&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;./queryGraphAPI.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// In case you don't have top level await yet&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;start&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;sharePointSite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;queryGraphApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sites/root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sharePointSite&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Complete.&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;Now if you start the program you should see a result like this:&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;npx ts-node index.ts
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s1"&gt;'@odata.context'&lt;/span&gt;: &lt;span class="s1"&gt;'https://graph.microsoft.com/v1.0/$metadata#sites/$entity'&lt;/span&gt;,
  createdDateTime: &lt;span class="s1"&gt;'2021-03-13T12:54:48.047Z'&lt;/span&gt;,
  description: &lt;span class="s1"&gt;''&lt;/span&gt;,
  &lt;span class="nb"&gt;id&lt;/span&gt;: &lt;span class="s1"&gt;'davelosert.sharepoint.com,0d19a070-63ba-40f8-872a-f83df5120b2a,770d1b68-3e43-44f2-aab4-ffc0bfe8c6a1'&lt;/span&gt;,
  lastModifiedDateTime: &lt;span class="s1"&gt;'2021-04-02T15:21:33Z'&lt;/span&gt;,
  name: &lt;span class="s1"&gt;''&lt;/span&gt;,
  webUrl: &lt;span class="s1"&gt;'https://davelosert.sharepoint.com'&lt;/span&gt;,
  displayName: &lt;span class="s1"&gt;'Communication site'&lt;/span&gt;,
  root: &lt;span class="o"&gt;{}&lt;/span&gt;,
  siteCollection: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;hostname&lt;/span&gt;: &lt;span class="s1"&gt;'davelosert.sharepoint.com'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
Complete.


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

&lt;/div&gt;

&lt;p&gt;Of course, this is just really simple code for a first working solution, but it's enough if you just need to query your data once in a while. If you plan to query the api more often, you might consider caching the token rather than requesting it on every query. The msal-library already supports caching&lt;br&gt;
by providing a plugin and you can find an example &lt;a href="https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md" rel="noopener noreferrer"&gt;on the Github Documentation&lt;/a&gt; – but covering this is out of scope of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Using the Graph-Explorer to find the right query
&lt;/h2&gt;

&lt;p&gt;Okay so now you should be able to query the SharePoint-Root-Site. However, I am pretty sure this is not the data you are after. So where to go from here?&lt;/p&gt;

&lt;p&gt;One option is to start looking in the &lt;a href="https://docs.microsoft.com/en-us/graph/api/overview?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Graph-API reference documentation&lt;/a&gt; to get an overview of what is possible.&lt;/p&gt;

&lt;p&gt;A more interactive and my recommended approach is using the &lt;a href="https://developer.microsoft.com/en-us/graph/graph-explorer" rel="noopener noreferrer"&gt;official Graph-Explorer&lt;/a&gt;. This browser-based application lets you play around with and query the Graph-API and get immediate feedback about the responses. This makes it a great tool to find out both, the &lt;strong&gt;exact path and query&lt;/strong&gt; as well as the &lt;strong&gt;permissions&lt;/strong&gt; you need for your use-case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfuoqyky9ejd64qvutpa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfuoqyky9ejd64qvutpa.png" alt="Screenshot of the Graph-Explorer with an executed search where the Modify permissions tab is selected"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Graph-Explorer is mostly self-explanatory, so I won't get into too much detail here. But an approach to find the right query might be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the left, select a &lt;strong&gt;Sample Query&lt;/strong&gt; that comes closest to what you are after&lt;/li&gt;
&lt;li&gt;Run the query.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You might need to give consent in the tab &lt;strong&gt;Modify permissions&lt;/strong&gt; so the Graph-Explorer is allowed to query the data in your name.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do you recognize this pattern? This is bascially the same as the admin-consent we gave in 1.3. – but this time for the Graph-Explorer App and rather than in the name of an admin, you give it in the name of **your&lt;/em&gt;* account.*&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Modify permissions&lt;/strong&gt; tab is also a great place to see which permissions are required to query the endpoint. However, it sometimes shows more permissions than you need.&lt;/p&gt;

&lt;p&gt;For example for the sample query &lt;em&gt;SharePoint Sites / my organization's default SharePoint Site&lt;/em&gt; (which is our query from Step 2), it shows both,&lt;br&gt;
&lt;strong&gt;Sites.Read.All&lt;/strong&gt; and &lt;strong&gt;Sites.ReadWrite.All&lt;/strong&gt;. But as we saw, the former is enough to read and the latter is only required if you also plan to write to SharePoint.&lt;/p&gt;

&lt;p&gt;Once you know which permissions you need, you can add them in the App registrations page like we did in Step 1.3.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refine the Query until the output matches what you are looking for.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;One last thing to consider:&lt;/strong&gt;&lt;br&gt;
As described, the Graph-Explorer runs in the context of your logged-in user, not your application. This means even if you &lt;strong&gt;consent&lt;/strong&gt; here, your App will not automatically get those permissions. As explained in 4., you still have to explicitly add them to your app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;As you might have seen, getting started with the Graph-API can be quite challenging. Especially the authentication and authorization part are a bit more complex to set up and not very intuitive at first.&lt;/p&gt;

&lt;p&gt;But once you know what to do and where to look, it is only some clicks and a few lines of code to make it work. For the serverless-function described in the intro, it took me hours to make it all work. But registering the application and setting up the code examples for this post only took me around 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So hopefully I reached my goal to save you the hours of work and get started with the Graph-API more quickly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As announced, I will soon publish a second blog-post where I'll go a bit deeper into the theory and concepts behind all of it.&lt;/p&gt;

&lt;p&gt;However, if you have any feedback or open questions, feel free to comment below and I'll answer as soon as possible.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>azure</category>
      <category>node</category>
      <category>graphapi</category>
    </item>
    <item>
      <title>Naming workarounds in code</title>
      <dc:creator>David Losert</dc:creator>
      <pubDate>Sun, 30 Aug 2020 10:32:52 +0000</pubDate>
      <link>https://dev.to/davelosert/naming-workarounds-in-code-312k</link>
      <guid>https://dev.to/davelosert/naming-workarounds-in-code-312k</guid>
      <description>&lt;p&gt;&lt;em&gt;Some weeks ago, I gave an advice in a code review to better mark a temporary workaround with a very long and descriptive function name. As I really like that approach, I want to share it with the world in this post.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why good naming is important
&lt;/h2&gt;

&lt;p&gt;First I want to talk briefly about why I think taking the time to find good names in code is so important.&lt;/p&gt;

&lt;p&gt;"Coding" to me usually means more reading or thinking than it means writing. I never measured this, but my feeling is that the ratio is even sometimes up to 95% reading (or thinking) and only 5% actively writing.&lt;/p&gt;

&lt;p&gt;This is especially true for bugs: I probably can't count how many times I tried to find the cause for a certain behavior or bug for hours – only then to fix it within a few seconds. &lt;/p&gt;

&lt;p&gt;But even in less extreme situations, I usually read way more than I write. And I am going out on a limb here and claim this is true for most coders.&lt;/p&gt;

&lt;p&gt;Following this logic we can say: the better readable our code is, the more efficient we will be writing it. And probably also have more fun in doing so. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  But what is readable code?
&lt;/h2&gt;

&lt;p&gt;Well, the bad news here is: It depends. Readability is really a subjective thing and you'll often find that what one person considers readable completely throws off another. &lt;/p&gt;

&lt;p&gt;Yet, I believe that there is a certain base level of practices with which you can achieve a overall better readability for a majority of readers. And that includes &lt;strong&gt;good and expressive variable and function names&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Just consider this basic example with non-expressive names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getExchangeRate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dollar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Euro&lt;/span&gt;&lt;span class="dl"&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;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;value&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;Just looking at the function name itself, one might understand that it is converting some value. But to know what it is converting, you have to read on.&lt;/p&gt;

&lt;p&gt;Seeing the call to &lt;code&gt;getExchangeRate&lt;/code&gt; and the multiplication of the value in the end, you can assume that the function converts money from one currency to another - the currencies being 'Dollar' and 'Euro'.&lt;/p&gt;

&lt;p&gt;But in which direction is it converting? Euro to Dollar or Dollar to Euro? Given the order of the arguments passed to &lt;code&gt;getExchangeRate&lt;/code&gt;, you might assume it's Dollar to Euros. But if you wanted to be sure about it you'd also have to look inside &lt;code&gt;getExchangeRate&lt;/code&gt;. Depdening on it's complexity, that might be a lot of reading.&lt;/p&gt;

&lt;p&gt;Now let's make this a bit clearer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertDollarToEuro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dollar&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;exchangeRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getExchangeRate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dollar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Euro&lt;/span&gt;&lt;span class="dl"&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;dollar&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;exchangeRate&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;Like this, all of the assumptions and questions we had before don't even come up. It is already clear that the function is converting dollars to euro just by it's name. Also within the function, the variable names are clearer in what they actually stand for.&lt;/p&gt;

&lt;p&gt;Of course this is a basic example - but if you stick to this kind of expressive names throughout your code, you will be able to read and navigate through it way faster.&lt;/p&gt;

&lt;h1&gt;
  
  
  The case at hand
&lt;/h1&gt;

&lt;p&gt;Now as wirtten in the introduction, I was doing a code review. The code was about mapping some data from an external API into our own object structure. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I simplified the example to focus on the method rather than the project itself So now it is about kittens.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code I reviewed looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&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;requestKittenFromApi&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;kitten&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;kittenAPIData&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="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;furrColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorOfFurr&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;homeTown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;
   &lt;span class="c1"&gt;// ... and many more mappings &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You might already have stumbled upon Line 5: Why is there a &lt;code&gt;or&lt;/code&gt; condition falling back to an empty string for the property &lt;code&gt;furrColor&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;My first assumption was that this it is setting a default value for an optional field. But why only for this line and not the others? &lt;/p&gt;

&lt;p&gt;As assumptions are evil, I went ahead and asked the developer who wrote it.&lt;/p&gt;

&lt;p&gt;As it turned out, this was only a workaround due to a bug in the API: Instead of returning the value for &lt;code&gt;furrColor&lt;/code&gt;, it was always returning null. And my assumption of it being optional was wrong as the rest of the code relied on it being set.&lt;/p&gt;

&lt;p&gt;The API Developers already knew about this bug and said they were going to fix this soon. So in this case, the workaround was a nice way to let them fix it whenver they want without having to synchronize our deployments. As soon as the API returned the correct values, our code would the right thing automatically.&lt;/p&gt;

&lt;p&gt;As much as I like developer communication, it would have been nice to avoid the confusion and extra effort of me asking by being able to see this is a workaround directly in the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to mark a workaround in code
&lt;/h2&gt;

&lt;p&gt;One thing that might come to mind are comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&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;requestKittenFromApi&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;kitten&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;kittenAPIData&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="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Defaulting to empty string is a workaround due to a bug in the API returning null&lt;/span&gt;
   &lt;span class="na"&gt;furrColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorOfFurr&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;homeTown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;
   &lt;span class="c1"&gt;// ... and many more mappings &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;p&gt;This is already better. But well - comments tend to get overlooked. At least I usually read logic first, comments (maybe) later. Also, as this was a bug that would get fixed soon, I wanted the next person stumbling upon this  to definitly check and maybe delete the then unecessary workaround.&lt;/p&gt;

&lt;p&gt;So why not use an expressive function name to mark it for what it is?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&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;requestKittenFromApi&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;kitten&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;kittenAPIData&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="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;furrColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultToEmptyStringAsTemporaryWorkaroundToBugInAPIReturningNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorOfFurr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;homeTown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kittenAPIData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;
   &lt;span class="c1"&gt;// ... and many more mappings &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;defaultToEmptyStringAsTemporaryWorkaroundToBugInAPIReturningNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colorOfFurr&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;colorOfFurr&lt;/span&gt; &lt;span class="o"&gt;||&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;Yes, you are seeing this correctly: A 63 character long function name explaining exactly what is going on. Did you get alerted by this? Well good - that was the intention. :)&lt;/p&gt;

&lt;p&gt;In my opinion, this approach has several advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It most definitly won't get overlooked by anyone&lt;/li&gt;
&lt;li&gt;If I'd stumble upon this, I'd definitly check if the bug still persists and delete the workaround if not&lt;/li&gt;
&lt;li&gt;It tells the reader not only &lt;strong&gt;what&lt;/strong&gt; is going, but also &lt;strong&gt;why&lt;/strong&gt; it is there in the first place&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now this approach shouldn't be used too often as it would then defy the purpose of alerting the reader. But I think it's a neat trick sometimes to really strike attention and let others or myself know that the written code here is not supposed to stay in forever. &lt;/p&gt;

&lt;p&gt;And as oppsed to just a comment that may even contain a &lt;code&gt;todo&lt;/code&gt;, this function name is really painful and gives a lot of motivation to refactor as soon as possible.&lt;/p&gt;

</description>
      <category>coding</category>
      <category>javascript</category>
      <category>cleancode</category>
      <category>developers</category>
    </item>
    <item>
      <title>Dependency Inversion with Redux-Thunk &amp; Typescript</title>
      <dc:creator>David Losert</dc:creator>
      <pubDate>Fri, 03 Jan 2020 10:22:10 +0000</pubDate>
      <link>https://dev.to/davelosert/dependency-inversion-with-redux-thunk-typescript-35k4</link>
      <guid>https://dev.to/davelosert/dependency-inversion-with-redux-thunk-typescript-35k4</guid>
      <description>&lt;p&gt;&lt;em&gt;In this article I will explain how we used Dependency Inversion to decouple all I/O modules in our React-Redux-Application resulting in the ability to completely change the Apps behavior by setting a Boolean during bootstrapp time.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I origanally published this blog post on medium two years ago - but as I like my content to be my own, I am republishing it now here ;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of my favorite and in my opinion most powerful software principles is the &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt; — or short DIP. It is the D in the famous SOLID Principles and it drives most patterns I know that take care of decoupling and modularization. Even more: Usage of the DIP actually makes the difference between a real OO-Design and a procedural one according to Robert C. Martin:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Indeed, it is this inversion of dependencies that is the hallmark of good object-oriented design. […]. If [a program’s] dependencies are inverted, it has an OO design. If its dependencies are not inverted, it has a procedural design.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Robert C. Martin — Agile Software Development: Principles, patterns and practices&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now some people might stop and say: But this article is about redux which celebrates functional programming. What do I care about OOP and OO-Design?&lt;/p&gt;

&lt;p&gt;In my opinion it doesn’t matter whether you use FP or OOP. Understanding and applying the DIP will help your tremendously in both disciplines, since you will always have to handle dependencies somehow — wether it is a class or a function.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Dependency Inversion?
&lt;/h2&gt;

&lt;p&gt;Before we go into the details, I’d like to give a brief introduction to dependency inversion. If you are already familiar with it, you can skip this section.&lt;/p&gt;

&lt;p&gt;As the name states, dependency inversion has to do with dependencies of classes / functions — more precisely with the abstraction of those dependencies.&lt;/p&gt;

&lt;p&gt;Lets look at an example: We use a classical App-Structure which has some sort of View, a Data Service and an API or Database-Service:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0htXuiw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fk0ftrvum9lz5m8zh3sn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0htXuiw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fk0ftrvum9lz5m8zh3sn.png" alt="Classical App Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;flow of control&lt;/em&gt; is like this: the &lt;strong&gt;View&lt;/strong&gt; reacts to a certain user-interaction by calling a function on the &lt;strong&gt;DataService&lt;/strong&gt; which itself calls a function of the &lt;strong&gt;API&lt;/strong&gt; or &lt;strong&gt;Database&lt;/strong&gt; to request some raw data, applies some domain rules before or after the call and then returns the data to the view.&lt;/p&gt;

&lt;p&gt;What we can see on the Diagram really well is that the dependency-chain exactly follows this control-flow — the View depends on the DataService which itself depends on the API.&lt;/p&gt;

&lt;p&gt;This is a problem though: As the DataService is part of our Domain and thus contains the fundamental rules of our application, it should not depend on anything else but other parts of the domain layer so that it stays testable, isolated an free of unecessary changes. After all, we expect the least changes to our domain and we want it to be the most stable part of our application, right?&lt;/p&gt;

&lt;p&gt;With this current way of implementation however, if the API changes only a bit, most likely the domain has to change as well. And since the view depends on the Domain, this will most likely have to change as well — meaning we’d have to touch several or all parts of our application if only one minor detail on one of the outer layers of our application changes. This kind of cascading changes are a lot of work that is actually not really necessary.&lt;/p&gt;

&lt;p&gt;Now lets see what can be done using an interface and thus applying DIP:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A76e2Qxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s4mrz1cb47u3g1qqt0tk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A76e2Qxs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/s4mrz1cb47u3g1qqt0tk.png" alt="App Structure with Dependency Inversion Applied"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By simply putting the interface &lt;strong&gt;DataRepository&lt;/strong&gt; between the domain service and the API, we already achieved a decoupled architecture. What is important here: The domain service owns that interface (or: the interface is part of our domain) while the API only implements it from the outside.&lt;/p&gt;

&lt;p&gt;That means the domain now only depends on itself (this is what we wanted) and only specifies what it needs from the outside world — but not how it needs it. The &lt;strong&gt;DataService&lt;/strong&gt; can work with anything that implements the &lt;strong&gt;DataRepository&lt;/strong&gt;-Interface — let it be a real database, a HTTP-API or simply an In-Memory-Repository with mock data. All that needs to be done is inject the right dependency during the bootstrapping phase of our app.&lt;/p&gt;

&lt;p&gt;Further: What we achieved now is that the &lt;strong&gt;ApiService&lt;/strong&gt; actually depends on the domain rather than the domain depending on the API. That means the direction of the dependencies is &lt;strong&gt;inverse&lt;/strong&gt; to the flow of control (red vs. black arrows) — hence the word &lt;strong&gt;Dependency Inversion&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is this done with Redux-Thunks?
&lt;/h2&gt;

&lt;p&gt;Now let’s transfer this to the classical react-redux application: There are some &lt;strong&gt;containers+components&lt;/strong&gt; (the view) which dispatches &lt;strong&gt;actions&lt;/strong&gt; (the domain) to redux to change the state. Some of those actions are asynchronous as they need to get certain data from an asynchronous API. A simple way of doing that is by using the redux-thunk middleware. Therefore, a simple app architecture could look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3L8DRP_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mgrmdszlxvbsiv40nk5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3L8DRP_O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mgrmdszlxvbsiv40nk5q.png" alt="Classical App Structure with React"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The implementing code might look like this (of course, it is one of our beloved Todo Apps):&lt;/p&gt;


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


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

&lt;p&gt;As in the abstract example before, the container (view) directly depends on the redux-thunk action (domain) which itself directly depends on the fetch-method (the API).&lt;/p&gt;

&lt;p&gt;The same problems from the abstract example arise now more clearly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The direct coupling lets the rather stable domain-code (the thunk) depend on the usually rather unstable API. Whenever the API changes just a little bit (a path changes), we will have to touch the thunk and it’s tests as well.&lt;/li&gt;
&lt;li&gt;By directly coupling the action to the API, testing this thunk is very hard (right now you would have to somehow mock the global fetch method)&lt;/li&gt;
&lt;li&gt;While developing, we don’t always have the luxury of an already existing or stable API and prefer to work with Mock-Data — our only chance to do so with this approach is to start some sort of JSON-Mock-Server that actually answers the HTTP-request on the correct URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So here we also want to use dependency inversion to abstract the API behind an interface and let the thunk only depend on that interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lets clean it up
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;For the gists in this example I pulled out the most important code snippets. You can find a full working implementation of the example in my Github Repository:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/davelosert"&gt;
        davelosert
      &lt;/a&gt; / &lt;a href="https://github.com/davelosert/di-with-redux"&gt;
        di-with-redux
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Example how to do dependency inversion with redux - used for a blog post
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The target structure should look something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DV1yFFpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/82tufa2wn7dl5fza54tq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DV1yFFpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/82tufa2wn7dl5fza54tq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So first, lets pull out a &lt;strong&gt;TodoRepository&lt;/strong&gt; Interface and create an &lt;strong&gt;APIService&lt;/strong&gt; named &lt;strong&gt;HttpTodoRepository&lt;/strong&gt; implementing it. Note how this simple refactoring already separates the role (being a repository for data) from the implementation and the used technology (use HTTP to fetch the data):&lt;/p&gt;


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


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

&lt;p&gt;Now we need to somehow pass in the &lt;strong&gt;HttpTodoService&lt;/strong&gt; as &lt;strong&gt;TodoRepository&lt;/strong&gt; to the thunk. We could do this by adding it to the parameters-list of the thunk itself — but that would mean all containers dispatching the action have to know about the service, and that is simply not their task (think &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsibility Pattern&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Luckily, redux-thunk allows us to specify a third parameter during bootstrap which will be passed to every called thunk. We can simply use that parameter as a &lt;strong&gt;dependency-injection&lt;/strong&gt; mechanism:&lt;/p&gt;


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

&lt;p&gt;And now we can use it in the thunk itself like so:&lt;/p&gt;


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

&lt;p&gt;The &lt;strong&gt;TodoRepository&lt;/strong&gt; is now the third parameter to the thunk-function. Further, the thunk-action knows nothing about the concrete implementation in &lt;strong&gt;HttpTodoRepository&lt;/strong&gt; anymore. We successfully decoupled the domain from the API.&lt;/p&gt;

&lt;p&gt;To see the real power of this abstraction, lets now also write a &lt;strong&gt;MockTodoRepository&lt;/strong&gt; implementing our &lt;strong&gt;TodoRepository&lt;/strong&gt; interface:&lt;/p&gt;


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

&lt;p&gt;All that is left to do now is pass the &lt;strong&gt;MockTodoRepository&lt;/strong&gt; instead of the &lt;strong&gt;HttpTodoRepository&lt;/strong&gt; when our store is created and the app suddenly works completely independent of internet connections and without a running API.&lt;/p&gt;

&lt;p&gt;This can be further improved by using a environment variable which will be passed from the outside to decide which of the two Repository-Implementation will be used:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
 

&lt;p&gt;The setting of this variable can be completely dynamic. We usually do it by using Webpack’s &lt;a href="https://webpack.js.org/plugins/define-plugin/"&gt;DefinePlugin&lt;/a&gt; where we set MOCK_API to either true or false depending on a given parameter at build time. This way, we can start our app in either mode from the CLI (&lt;code&gt;npm start&lt;/code&gt; vs. &lt;code&gt;npm start:mock&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;With one simple variable, we can now completely change our apps data-behavior while not changing its logical behavior at all. With this architecture, changing your API from REST to GraphQL or from HTTP to HTTP2 is nothing more than writing a new service implementing the &lt;strong&gt;DataRepository&lt;/strong&gt; Interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  But how does this scale?
&lt;/h2&gt;

&lt;p&gt;We are actually using this architecture in a bigger application and made some very good experiences with it. To be able to scale, we are actually not injecting the APIService itself, but (also environment specific) Factory holding all our dependencies. That way, every thunk has the possibility to request whatever dependency it needs instead of just the API.&lt;/p&gt;

&lt;p&gt;When our API wasn’t available for two weeks, we still could develop our frontend app easily and even let our POs test it logically by faking backend behavior with an In-memory API (so Create/Update/Delete operations where possible).&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;you can use redux-thunk’s &lt;code&gt;thunk.withExtraArgument(deps)&lt;/code&gt; function as a dependency injection mechanism&lt;/li&gt;
&lt;li&gt;to avoid tight coupling, let your thunk (or your domain) specify the dependencies it needs as interfaces, not as already concrete implementations&lt;/li&gt;
&lt;li&gt;implement those interfaces elsewhere and pass them into the thunks with the function above during bootstrapping&lt;/li&gt;
&lt;li&gt;use environment variables (e.g. set by Webpacks DefinePlugin) to decide which implementation of your domain-interfaces you pass into the app to control your apps behavior on the highest level&lt;/li&gt;
&lt;/ul&gt;

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