<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Bart Verkoeijen</title>
        <link>https://bgever.com/</link>
        <description>Notes on web development, software craft, and building things — by Bart Verkoeijen, a Dutch software engineer based in Hong Kong.</description>
        <lastBuildDate>Sat, 01 Aug 2026 09:45:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>Content licensed CC BY-NC-SA 4.0 — Bart Verkoeijen</copyright>
        <atom:link href="https://bgever.com/rss.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Hello World, again!]]></title>
            <link>https://bgever.com/2021/hello-world-again</link>
            <guid isPermaLink="false">https://bgever.com/2021/hello-world-again</guid>
            <pubDate>Sat, 03 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Motivations for why I started blogging again]]></description>
            <content:encoded><![CDATA[<p>A few weeks ago I saw my very first website again, thanks to the good folks at the Internet Archive. It sparked nostalgia and it also reminded me on how much fun I had publishing to the web. That got me thinking.</p>
<p>Thinking why I stopped writing, even though I had such fond memories of it. The pandemic gave me that opportunity to pause, reflect, and realize what things I used to value. Glad to see that something good is coming out of this mess.</p>
<p>I’ll list out my motivations, as a reminder for myself, and it may possibly inspire you to take up blogging too, dear reader.</p>
<h2 id="the-enjoyment-of-writing" tabindex="-1">The enjoyment of writing <a class="header-anchor" href="#the-enjoyment-of-writing" aria-label="Permalink to &quot;The enjoyment of writing&quot;">&ZeroWidthSpace;</a></h2>
<p>Back in 2002 when I was a student, I was experimenting a lot with the web. Learning about HTML, CSS, PHP and documenting the process. I shared my experiences on a particular forum (good old phpBB) with other developers in the Dutch web community. People had feedback, got inspired themselves, and there was always a healthy discussion. That motivated me to take up a career in web development. I believe that positive experience led to a positive association to writing for me.</p>
<p>However, there’s more depth to it than that, and that leads me to these benefits.</p>
<h3 id="investigative-learning" tabindex="-1">Investigative learning <a class="header-anchor" href="#investigative-learning" aria-label="Permalink to &quot;Investigative learning&quot;">&ZeroWidthSpace;</a></h3>
<p>Taking a moment to dig a bit deeper to find out why things are the way they are, can lead to a breakthrough in my thought process. Too often in this fast paced world we take things for granted. It helps to make time to allow for our mind to wander, to go into different directions, and spark innovations. Investigating deeper, learning about things. I find that unearthing something new feels fantastic. It probably has to do something with dopamine, my guess.</p>
<h3 id="calm-the-mind" tabindex="-1">Calm the mind <a class="header-anchor" href="#calm-the-mind" aria-label="Permalink to &quot;Calm the mind&quot;">&ZeroWidthSpace;</a></h3>
<p>Putting thoughts to paper helps to put my mind to rest. Knowing that the thoughts are deposited somewhere, ready for the taking later. Especially since I’m a knowledge worker, having to work with my mind all day.</p>
<p>This means that the writeup may not be intended for others to read. It’s okay when there isn’t an immediate audience. I do it for self care.</p>
<h3 id="writing-exercise" tabindex="-1">Writing exercise <a class="header-anchor" href="#writing-exercise" aria-label="Permalink to &quot;Writing exercise&quot;">&ZeroWidthSpace;</a></h3>
<p>Formulating words in a cohesive, short, and informative matter helps my overall communication skills. Going from rambling thoughts to manicured words takes practice. After writing more, I’ve observed it becomes easier to immediately formulate my thoughts. That helps me to have better in-person conversations too.</p>
<h2 id="the-reward-of-writing" tabindex="-1">The reward of writing <a class="header-anchor" href="#the-reward-of-writing" aria-label="Permalink to &quot;The reward of writing&quot;">&ZeroWidthSpace;</a></h2>
<p>Looking back at when I was writing those years ago, and also thinking of similar experiences doing talks and presentations, there are nice rewards to reap after putting in the effort.</p>
<h3 id="progress-as-a-motivator" tabindex="-1">Progress as a motivator <a class="header-anchor" href="#progress-as-a-motivator" aria-label="Permalink to &quot;Progress as a motivator&quot;">&ZeroWidthSpace;</a></h3>
<p>It is motivating to see how I’ve grown and made progress over the years. Especially when in the tech industry it’s hard to avoid the imposter syndrome. Moreover, it invokes nostalgia, and is a good reminder that in life it is about the journey, and not the destination.</p>
<h3 id="celebrate-milestones" tabindex="-1">Celebrate milestones <a class="header-anchor" href="#celebrate-milestones" aria-label="Permalink to &quot;Celebrate milestones&quot;">&ZeroWidthSpace;</a></h3>
<p>I’ve often spent countless hours resolving a problem. When I do finally find the solution, the achievement can feel empty. Not all tech solutions surface itself in the UI, and documenting it in writing can give that sense of accomplishment.</p>
<h3 id="reference-material" tabindex="-1">Reference material <a class="header-anchor" href="#reference-material" aria-label="Permalink to &quot;Reference material&quot;">&ZeroWidthSpace;</a></h3>
<p>There have been times I found my own StackOverflow answers after an internet search. Or have been able to help a fellow dev pointing to my experiences. With a catalog of blog posts it becomes easier to tap into my past experiences.</p>
<h2 id="the-side-effects-of-writing" tabindex="-1">The side-effects of writing <a class="header-anchor" href="#the-side-effects-of-writing" aria-label="Permalink to &quot;The side-effects of writing&quot;">&ZeroWidthSpace;</a></h2>
<p>There are benefits of not keeping my thoughts to myself. It’s a vulnerable but humbling experience. It’s similar to speaking. Anyone who has stood in front of a large audience preaching their thoughts knows the anxiety. But also likely experienced the appreciation you get in return.</p>
<h3 id="community-engagement" tabindex="-1">Community engagement <a class="header-anchor" href="#community-engagement" aria-label="Permalink to &quot;Community engagement&quot;">&ZeroWidthSpace;</a></h3>
<p>Software development is quite a solitary job. It is nice when I can reach out to other like-minded people. Confirmation and constructive feedback can help everyone grow. Being a lone wolf doesn’t help. Opening up to others broadens my horizons.</p>
<p>In addition it will grow my professional network. It allows me to meet other inspirational people. Especially when I share my content on other professional social networks also.</p>
<h3 id="showcases-experience" tabindex="-1">Showcases experience <a class="header-anchor" href="#showcases-experience" aria-label="Permalink to &quot;Showcases experience&quot;">&ZeroWidthSpace;</a></h3>
<p>And finally, after a while documenting the processes and problems and solutions I encounter, it becomes a nice showcase of my experience. Something that can’t easily be shared in a job interview. Therefore the blog becomes an extension of my CV.</p>
<hr>
<p>This should all be plenty of reasons to keep me motivated to persist with writing on this blog. Looking forward to the journey ahead, and thank you for joining me on the ride.</p>
]]></content:encoded>
            <author>Bart Verkoeijen</author>
            <category>personal</category>
            <enclosure url="https://bgever.com/covers/hello-world-again.webp" length="0" type="image/webp"/>
        </item>
        <item>
            <title><![CDATA[Making the Auth0 SPA SDK unit testable with Angular]]></title>
            <link>https://bgever.com/2019/making-the-auth0-spa-sdk-unit-testable-with-angular</link>
            <guid isPermaLink="false">https://bgever.com/2019/making-the-auth0-spa-sdk-unit-testable-with-angular</guid>
            <pubDate>Thu, 31 Oct 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[The Auth0 Angular Quick Start hides the client behind a promise, which makes it awkward to mock. An InjectionToken turns it into a constructor dependency you can stub and spy on.]]></description>
            <content:encoded><![CDATA[<p><a href="https://auth0.com/" target="_blank" rel="noreferrer">Auth0</a>, the authentication service and identity provider has a new <a href="https://auth0.com/docs/libraries/auth0-spa-js" target="_blank" rel="noreferrer">SDK for Single Page Applications</a> (SPAs) that works well with Angular. Their dashboard has an Angular Quick Start, and in it they provide a tailored wrapper class for Angular to work with their SDK. When you extend this class you may run into the issue that you can't easily mock the <code>Auth0Client</code> dependency. Read on to find out how to do this.</p>
<!-- more -->
<p>Part of the provided <code>AuthService</code> class looks like below.</p>
<div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">@</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">Injectable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">({</span><span style="--shiki-light:#998418;--shiki-dark:#B8A965">providedIn</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">root</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#999999;--shiki-dark:#666666">})</span></span>
<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">export</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676"> class</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994"> AuthService</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">  // Create an observable of Auth0 instance of client</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">  auth0Client$</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> (</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">from</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">    createAuth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">({</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">      domain</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">"</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">example.auth0.com</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">"</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">      client_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">"</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">ABC123abc123abc123ABC</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">"</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">      redirect_uri</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">`</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">${</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">window</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">location</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">origin</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">}</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">`</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    })</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  )</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375"> as</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994"> Observable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">Auth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">>).</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">pipe</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">    shareReplay</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666">),</span><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD"> // Every sub receives the same shared value</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">    catchError</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">err</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#59873A;--shiki-dark:#80A665"> throwError</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">err</span><span style="--shiki-light:#999999;--shiki-dark:#666666">))</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  );</span></span></code></pre>
</div><p>The problem lies with the <code>createAuth0Client</code> function that is imported from the SDK. It provides access to the client object via a promise. Angular heavily depends on RXJS however, and to transform this into an observable, the <code>from</code> helper function is used. Other properties in the class are then chained to this observable to provide the authentication functionality.</p>
<p>For unit testing this is a dilemma, as it poses an external dependency that cannot be accessed. It is similar to directly using the browser's <code>document</code> object versus an injected <code>Document</code> reference in your Angular code. Instead, when the class is created, this external dependency should be injectable via the constructor so that the object can be mocked and spied upon.</p>
<h2 id="injecting-the-auth0client-observable" tabindex="-1">Injecting the Auth0Client observable <a class="header-anchor" href="#injecting-the-auth0client-observable" aria-label="Permalink to &quot;Injecting the Auth0Client observable&quot;">&ZeroWidthSpace;</a></h2>
<p>Since the <code>Auth0Client</code> is loaded asynchronously with a promise that is wrapped as an observable, it may seem impossible to create a dependency in the constructor to <code>Observable&lt;Auth0Client&gt;</code>. However, this is possible in Angular through the use of an <code>InjectionToken</code>.</p>
<p>As of Angular 6, the <code>InjectionToken</code> is now tree shakable and can leverage a factory function. That makes it easy to define our injectable token:</p>
<div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">export</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676"> const </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">AUTH0_CLIENT</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span></span>
<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">  new </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">InjectionToken</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">Observable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">Auth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">>>(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">auth0Client$</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">    providedIn</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">root</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">    factory</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: () => </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">from</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">      createAuth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">({</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">        domain</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">environment</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">auth0</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">domain</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">        client_id</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">environment</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">auth0</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientId</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">        audience</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">environment</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">auth0</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">audience</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#998418;--shiki-dark:#B8A965">        redirect_uri</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">REDIRECT_URI</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">      })</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    ).</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">pipe</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">      shareReplay</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666">), </span><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">// Every sub receives the same shared value</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">      catchError</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">err</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> => </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">throwError</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">err</span><span style="--shiki-light:#999999;--shiki-dark:#666666">))</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    )</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  });</span></span></code></pre>
</div><p>Next, this token can now be injected into the constructor of the <code>AuthService</code> class:</p>
<div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">constructor</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">  // Use an injection token to get an observable instance</span></span>
<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">  // of the Auth0 client.</span></span>
<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE">  @</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">Inject</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">AUTH0_CLIENT</span><span style="--shiki-light:#999999;--shiki-dark:#666666">)</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">  private</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A"> auth0Client$</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE">: </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Observable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Auth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">>,</span></span></code></pre>
</div><p>Because the token was marked with <code>provideIn</code>, and referenced in the injectable <code>AuthService</code>, it is discovered during build and included in the compilation. There is no need to expose it with a provider in a module.</p>
<h2 id="mocking-the-auth0client-in-unit-tests" tabindex="-1">Mocking the Auth0Client in unit tests <a class="header-anchor" href="#mocking-the-auth0client-in-unit-tests" aria-label="Permalink to &quot;Mocking the Auth0Client in unit tests&quot;">&ZeroWidthSpace;</a></h2>
<p>With the introduction of TypeScript's <code>Partial</code> interface, it became a whole lot easier to mock type-safe partial implementations. With it we can mock for instance only one class function. We then can wrap that into an observable with the <code>of</code> helper function, and inject that into the <code>AuthService</code>.</p>
<div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">const </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676"> of</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Partial</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Auth0Client</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">>></span><span style="--shiki-light:#999999;--shiki-dark:#666666">({</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">  getTokenSilently</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">async</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> () => </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">null</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">beforeEach</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(()</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">  service</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676"> new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665"> AuthService</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    &#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Observable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Auth0Client</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">>></span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">    // etc...</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  );</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">});</span></span></code></pre>
</div><p>The above code mocks the result of the <code>getTokenSilently</code> function, to return a promise with an undefined token.</p>
<p>With this method it is also easy to spy on the mocks as well:</p>
<div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code" tabindex="0" v-pre=""><code><span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">const </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> &#x3C;</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">Partial</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">Auth0Client</span><span style="--shiki-light:#999999;--shiki-dark:#666666">>>{</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">  getTokenSilently</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">async</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> () => </span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">null</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">};</span></span>
<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">const </span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub$</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665"> of</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">beforeEach</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(()</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">  spyOn</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77"> '</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">getTokenSilently</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#999999;--shiki-dark:#666666">).</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">and</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">callThrough</span><span style="--shiki-light:#999999;--shiki-dark:#666666">();</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">  service</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676"> new</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665"> AuthService</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    &#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Observable</span><span style="--shiki-light:#999999;--shiki-dark:#666666">&#x3C;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">Auth0Client</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676">>></span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub$</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span></span>
<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD">    // etc...</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  );</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">it</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">should handle custom initialization</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">'</span><span style="--shiki-light:#999999;--shiki-dark:#666666">,</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> (</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">done</span><span style="--shiki-light:#999999;--shiki-dark:#666666">: </span><span style="--shiki-light:#2E8F82;--shiki-dark:#5DA994">DoneFn</span><span style="--shiki-light:#999999;--shiki-dark:#666666">)</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">  service</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">init</span><span style="--shiki-light:#999999;--shiki-dark:#666666">().</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">subscribe</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    ()</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#999999;--shiki-dark:#666666"> {</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">      expect</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">clientStub</span><span style="--shiki-light:#999999;--shiki-dark:#666666">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">getTokenSilently</span><span style="--shiki-light:#999999;--shiki-dark:#666666">).</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665">toHaveBeenCalled</span><span style="--shiki-light:#999999;--shiki-dark:#666666">();</span></span>
<span class="line"><span style="--shiki-light:#59873A;--shiki-dark:#80A665">      done</span><span style="--shiki-light:#999999;--shiki-dark:#666666">();</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">    },</span></span>
<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A">    error</span><span style="--shiki-light:#999999;--shiki-dark:#666666"> =></span><span style="--shiki-light:#59873A;--shiki-dark:#80A665"> fail</span><span style="--shiki-light:#999999;--shiki-dark:#666666">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">`</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">Unexpected error: </span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">${</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D">error</span><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375">}</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77">`</span><span style="--shiki-light:#999999;--shiki-dark:#666666">)</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">  );</span></span>
<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666">});</span></span></code></pre>
</div><p>Hopefully this gave you insight how to extend the <code>AuthService</code> class to make it possible to unit test it better.</p>
<p>Thanks for reading!</p>
]]></content:encoded>
            <author>Bart Verkoeijen</author>
            <category>angular</category>
            <category>auth0</category>
            <category>unit-testing</category>
        </item>
    </channel>
</rss>