<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2024-03-23T13:11:45+00:00</updated><id>/feed.xml</id><title type="html">Test Bitten Dev</title><subtitle>Thoughts about unit testing</subtitle><author><name>Serhii Shushliapin</name></author><entry><title type="html">SXA CLI Installation Troubleshooting</title><link href="/2024/02/08/sxa-cli-installation-troubleshooting" rel="alternate" type="text/html" title="SXA CLI Installation Troubleshooting" /><published>2024-02-08T14:08:00+00:00</published><updated>2024-02-08T14:08:00+00:00</updated><id>/2024/02/08/sxa-cli-installation-troubleshooting</id><content type="html" xml:base="/2024/02/08/sxa-cli-installation-troubleshooting"><![CDATA[<p>While the installation process for SXA CLI appears straightforward and is documented in various blog posts (such as <a href="https://www.markvanaalst.com/blog/sxa/installing-the-sitecore-sxa-cli">here</a> or <a href="https://www.getfishtank.com/blog/install-sxa-theme-in-sitecore-docker-mvc-sxa-10">here</a>), I encountered several issues that necessitated additional steps. Below, I outline these challenges and their resolutions.</p>

<h2 id="python-dependency">Python Dependency</h2>

<p>Surprisingly, neither the blog posts nor the <a href="https://doc.sitecore.com/xp/en/developers/sxa/103/sitecore-experience-accelerator/add-a-theme-using-sxa-cli.html">official Sitecore documentation</a> mentioned Python as a prerequisite. Upon attempting to install SXA CLI using the <code class="language-plaintext highlighter-rouge">npm i -g @sitecore/sxa-cli</code> command, I encountered the following error:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm ERR! gyp ERR! find Python ********************************************************
npm ERR! gyp ERR! find Python You need to install the latest version of Python.
npm ERR! gyp ERR! find Python Node-gyp should be able to find and use Python. If not,
npm ERR! gyp ERR! find Python you can try one of the following options:
...
</code></pre></div></div>

<p>Following the provided instructions, I downloaded and installed the latest Python version (3.12.2 as of February 6, 2024), ensuring to select ‘Add python.exe to PATH’ during installation.</p>

<p><img src="/assets/img/2024-02-08-python-versions.png" alt="alt text" /></p>

<p>Although this resolved the error, the Python-related issue persisted. More on this later. Let’s address the next challenge.</p>

<h2 id="desktop-development-with-c-workload">“Desktop development with C++” Workload</h2>

<p>Another hurdle emerged due to the absence of the “Desktop development with C++” workload, a requirement that can be fulfilled through the Visual Studio Installer.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm ERR! gyp ERR! find VS ************************************************************
npm ERR! gyp ERR! find VS You need to install the latest version of Visual Studio
npm ERR! gyp ERR! find VS including the "Desktop development with C++" workload.
npm ERR! gyp ERR! find VS For more information consult the documentation at:
npm ERR! gyp ERR! find VS https://github.com/nodejs/node-gyp#on-windows
npm ERR! gyp ERR! find VS ************************************************************
</code></pre></div></div>

<p>Despite enabling this workload initially, the error persisted. Upon closer inspection of the logs, I discovered that the Windows SDK was missing. Selecting the appropriate checkbox in the installer resolved the issue.</p>

<p><img src="/assets/img/2024-02-08-vs-installer.png" alt="alt text" /></p>

<h2 id="revisiting-the-python-issue">Revisiting the Python Issue</h2>

<p>With the Visual Studio obstacle cleared, a new Python-related error surfaced:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm ERR! ModuleNotFoundError: No module named 'distutils'
npm ERR! gyp ERR! configure error
npm ERR! gyp ERR! stack Error: `gyp` failed with exit code: 1
</code></pre></div></div>

<p>Further investigation revealed that the <code class="language-plaintext highlighter-rouge">distutils</code> library had been deprecated and removed in Python 3.12. A comprehensive discussion on potential solutions can be found <a href="https://stackoverflow.com/questions/69919970/no-module-named-distutils-but-distutils-installed">here</a>. Ultimately, downgrading to Python 3.11.8 resolved the issue.</p>]]></content><author><name>Serhii Shushliapin</name></author><category term="sxa" /><summary type="html"><![CDATA[While the installation process for SXA CLI appears straightforward and is documented in various blog posts (such as here or here), I encountered several issues that necessitated additional steps. Below, I outline these challenges and their resolutions.]]></summary></entry><entry><title type="html">Configuring item children</title><link href="/2020/01/11/configuring-item-children" rel="alternate" type="text/html" title="Configuring item children" /><published>2020-01-11T09:54:00+00:00</published><updated>2020-01-11T09:54:00+00:00</updated><id>/2020/01/11/configuring-item-children</id><content type="html" xml:base="/2020/01/11/configuring-item-children"><![CDATA[<p>Probably one of the most used item operations is requesting its children. FakeDb typically configures item hierarchy in the <a href="https://github.com/sshushliapin/Sitecore.FakeDb/wiki/Creating-a-Hierarchy-of-Items">db context setup</a> block (see <code class="language-plaintext highlighter-rouge">using</code> statement). Likely, for mocks that is not needed. In this post I’ll show few advanced ways to extend <code class="language-plaintext highlighter-rouge">ItemCustomization</code> in order to add subitems to a mocked item.</p>

<h3 id="fakedb-style">FakeDb style</h3>

<p>Let’s refresh in mind how does FakeDb-style hierarchy look like:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Fact</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">HowToCreateHierarchyOfItems</span><span class="p">()</span>
<span class="p">{</span>
  <span class="k">using</span> <span class="p">(</span><span class="n">Sitecore</span><span class="p">.</span><span class="n">FakeDb</span><span class="p">.</span><span class="n">Db</span> <span class="n">db</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Sitecore</span><span class="p">.</span><span class="n">FakeDb</span><span class="p">.</span><span class="n">Db</span>
    <span class="p">{</span>
      <span class="k">new</span> <span class="n">Sitecore</span><span class="p">.</span><span class="n">FakeDb</span><span class="p">.</span><span class="nf">DbItem</span><span class="p">(</span><span class="s">"Articles"</span><span class="p">)</span>
        <span class="p">{</span>
          <span class="k">new</span> <span class="n">Sitecore</span><span class="p">.</span><span class="n">FakeDb</span><span class="p">.</span><span class="nf">DbItem</span><span class="p">(</span><span class="s">"Getting Started"</span><span class="p">),</span>
          <span class="k">new</span> <span class="n">Sitecore</span><span class="p">.</span><span class="n">FakeDb</span><span class="p">.</span><span class="nf">DbItem</span><span class="p">(</span><span class="s">"Troubleshooting"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">})</span>
  <span class="p">{</span>
    <span class="n">Sitecore</span><span class="p">.</span><span class="n">Data</span><span class="p">.</span><span class="n">Items</span><span class="p">.</span><span class="n">Item</span> <span class="n">articles</span> <span class="p">=</span>
      <span class="n">db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/Articles"</span><span class="p">);</span>

    <span class="n">Xunit</span><span class="p">.</span><span class="n">Assert</span><span class="p">.</span><span class="nf">NotNull</span><span class="p">(</span><span class="n">articles</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Getting Started"</span><span class="p">]);</span>
    <span class="n">Xunit</span><span class="p">.</span><span class="n">Assert</span><span class="p">.</span><span class="nf">NotNull</span><span class="p">(</span><span class="n">articles</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Troubleshooting"</span><span class="p">]);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Looks pretty but it takes a while to get to the line of code where we can actually retrieve some children. As usual, db context needs to be created. Then we have to add root item, two child items and finally retrieve the root from the database.</p>

<p>With mocks and AutoFixture, children can be created in a <em>single</em> line of code using <code class="language-plaintext highlighter-rouge">root.Children.InnerChildren</code> property. Let’s leave the question if that’s a good design to reveal <a href="https://enterprisecraftsmanship.com/posts/what-is-implementation-detail/">internal implementation details</a> hanging in the air. For us it’s a back door that allows to add children to an item. Just compare this with the previous sample:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetChildren</span><span class="p">(</span>
    <span class="n">Item</span> <span class="n">root</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">child1</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">child2</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child1</span><span class="p">,</span> <span class="n">child2</span> <span class="p">});</span>

    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child1</span><span class="p">,</span> <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="n">child1</span><span class="p">.</span><span class="n">ID</span><span class="p">]);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child2</span><span class="p">,</span> <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="n">child2</span><span class="p">.</span><span class="n">ID</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>That was the minimal working example. In case we need child names, the test can be slightly extended:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetChildrenByName</span><span class="p">(</span>
    <span class="n">Item</span> <span class="n">root</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">child1</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">child2</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">child1</span><span class="p">.</span><span class="n">Name</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="s">"Getting Started"</span><span class="p">);</span>
    <span class="n">child2</span><span class="p">.</span><span class="n">Name</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="s">"Troubleshooting"</span><span class="p">);</span>

    <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child1</span><span class="p">,</span> <span class="n">child2</span> <span class="p">});</span>

    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child1</span><span class="p">,</span> <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Getting Started"</span><span class="p">]);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child2</span><span class="p">,</span> <span class="n">root</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Troubleshooting"</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="extending-item-customization-with-children-property">Extending Item Customization with Children property</h3>

<p>As you could’ve notice, any new scenario requires some extension of the <code class="language-plaintext highlighter-rouge">ItemCustomization</code> class we created <a href="/2019/12/30/testing-content-tree-via-mocked-item-axes.html#extending-item-customization">before</a>. ATM, the <code class="language-plaintext highlighter-rouge">item.Children</code> collection is null and needs to be configured. The following line of code must be added to the <code class="language-plaintext highlighter-rouge">CreateItem</code> method:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">ItemCustomization</span> <span class="p">:</span> <span class="n">ICustomization</span>
<span class="p">{</span>
    <span class="p">...</span>

    <span class="k">private</span> <span class="k">static</span> <span class="n">Item</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">ID</span> <span class="n">id</span><span class="p">,</span> <span class="n">ItemData</span> <span class="n">itemData</span><span class="p">,</span> <span class="n">Database</span> <span class="n">database</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="p">...</span>
        <span class="n">item</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">ChildList</span><span class="p">&gt;(</span><span class="n">item</span><span class="p">,</span> <span class="k">new</span> <span class="nf">ItemList</span><span class="p">()));</span>
        <span class="k">return</span> <span class="n">item</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>All the tests above pass. Item returns a collection of children but there is one thing worth to be mentioned.</p>

<h3 id="mocks-are-not-fakes">Mocks are not fakes</h3>

<p>As it says, <a href="https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da">mocks are not fakes</a>. It means that the testing approach described above requires manual configuration of <em>all</em> the api calls. There is no any Sitecore logic running behind the scene. For instance, injecting some items into <code class="language-plaintext highlighter-rouge">item.Children</code> collection does not make <code class="language-plaintext highlighter-rouge">item.HasChildren</code> to return true. It will return false unless this specific call is configured:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetChildrenVsOtherProps</span><span class="p">(</span><span class="n">Item</span> <span class="n">parent</span><span class="p">,</span> <span class="n">Item</span> <span class="n">child</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child</span> <span class="p">});</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">NotEmpty</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span> <span class="c1">// fails</span>

    <span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span> <span class="c1">// passes</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Same is valid for child parent props. If you want to call <code class="language-plaintext highlighter-rouge">Parent</code> or <code class="language-plaintext highlighter-rouge">ParentID</code>, the props must be set in advance:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">ChildrenParentProps</span><span class="p">(</span><span class="n">Item</span> <span class="n">parent</span><span class="p">,</span> <span class="n">Item</span> <span class="n">child</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child</span> <span class="p">});</span>
    <span class="n">child</span><span class="p">.</span><span class="n">Parent</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">parent</span><span class="p">);</span>
    <span class="n">child</span><span class="p">.</span><span class="n">ParentID</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">);</span>

    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">child</span><span class="p">.</span><span class="n">Parent</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">,</span> <span class="n">child</span><span class="p">.</span><span class="n">ParentID</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The pure mocks described above are sufficient and can be successfully used in real projects. This approach is straightforward. Tests suppose to configure all the methods/props needed for SUT which makes clear what is going on. Disadvantage might be the necessity to configure few relative props which sometimes might look awkward.</p>

<h3 id="mixed-approach">Mixed approach</h3>

<p>It is possible to combine both techniques. We can use mocked items and add some fake logic to related properties. That would reduce the amount of configuration code. See how adding a child could impact <code class="language-plaintext highlighter-rouge">HasChildren</code> property. In the <code class="language-plaintext highlighter-rouge">ItemCustomization</code>, add the following line:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">ItemCustomization</span> <span class="p">:</span> <span class="n">ICustomization</span>
<span class="p">{</span>
    <span class="p">...</span>
    <span class="k">private</span> <span class="k">static</span> <span class="n">Item</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">ID</span> <span class="n">id</span><span class="p">,</span> <span class="n">ItemData</span> <span class="n">itemData</span><span class="p">,</span> <span class="n">Database</span> <span class="n">database</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="p">...</span>
        <span class="n">item</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">c</span> <span class="p">=&gt;</span> <span class="n">item</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">Any</span><span class="p">());</span>
        <span class="k">return</span> <span class="n">item</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This changes test behavior. The <code class="language-plaintext highlighter-rouge">HasChildren</code> property cannot (!) be configured in test anymore (TBH, that was a surprise to me so I might need to get back to this later). Instead, what you can do is to add/remove child items and observe the prop value change:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetChildrenWithFakeProps</span><span class="p">(</span><span class="n">Item</span> <span class="n">parent</span><span class="p">,</span> <span class="n">Item</span> <span class="n">child</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child</span> <span class="p">});</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span> <span class="c1">// pass</span>

    <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">Clear</span><span class="p">();</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">False</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span> <span class="c1">// pass</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="configuring-related-props-via-extension-methods">Configuring related props via extension methods</h4>

<p>Further step might be to introduce some simple logic to set all the related properties at once. For instance, new <code class="language-plaintext highlighter-rouge">AddRange</code> extension method can set child’s <code class="language-plaintext highlighter-rouge">Parent</code> and <code class="language-plaintext highlighter-rouge">ParentID</code> props (the code snippet below assumes <code class="language-plaintext highlighter-rouge">HasChildren</code> is already configured via mocks as shown earlier):</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">AddChildrenWithFakeProps</span><span class="p">(</span><span class="n">Item</span> <span class="n">parent</span><span class="p">,</span> <span class="n">Item</span> <span class="n">child</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">.</span><span class="nf">AddRange</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">child</span> <span class="p">});</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">child</span><span class="p">.</span><span class="n">Parent</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">,</span> <span class="n">child</span><span class="p">.</span><span class="n">ParentID</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">internal</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">ChildListExtensions</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="nf">AddRange</span><span class="p">(</span><span class="k">this</span> <span class="n">ChildList</span> <span class="n">childList</span><span class="p">,</span> <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">Item</span><span class="p">&gt;</span> <span class="n">newItems</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">parent</span> <span class="p">=</span> <span class="n">childList</span><span class="p">.</span><span class="n">OwnerItem</span><span class="p">;</span>
        <span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="n">newItems</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">childList</span><span class="p">.</span><span class="n">InnerChildren</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
            <span class="n">item</span><span class="p">.</span><span class="n">Parent</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">parent</span><span class="p">);</span>
            <span class="n">item</span><span class="p">.</span><span class="n">ParentID</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>I’d like to highlight that as soon as the fake logic behind mocks is trivial it’s ok to keep it in the test code base. If you find it too complex and does not wish to invest time into maintaining it over time, you might be interesting in the ready-to-use library like <a href="https://github.com/smarchenko/SitecoreDI.NSubstitute.Helper">Sitecore.NSubstituteUtils</a> created by <a href="https://github.com/smarchenko">@smar</a>.</p>

<h4 id="configuring-related-props-using-sitecorensubstituteutils">Configuring related props using Sitecore.NSubstituteUtils</h4>

<p>While all the samples above can be implemented in any testing suite, there are some public libraries that can do pretty much the same things OOTB. There is an example of item structure created with <a href="https://github.com/smarchenko/SitecoreDI.NSubstitute.Helper#creating-item-and-structures-of-items">Sitecore.NSubstituteUtils</a>:</p>

<p><strong>[UPDATED 13-Jan-2020]:</strong> Removed unnecessary <code class="language-plaintext highlighter-rouge">(Item)</code> type cast.</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">ConfigureChildrenViaNSubstituteHelper</span><span class="p">(</span>
    <span class="n">FakeItem</span> <span class="n">parentFake</span><span class="p">,</span>
    <span class="n">FakeItem</span> <span class="n">child1Fake</span><span class="p">,</span>
    <span class="n">FakeItem</span> <span class="n">child2Fake</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Item</span> <span class="n">parent</span> <span class="p">=</span> <span class="n">parentFake</span><span class="p">.</span><span class="nf">WithChild</span><span class="p">(</span><span class="n">child1Fake</span><span class="p">).</span><span class="nf">WithChild</span><span class="p">(</span><span class="n">child2Fake</span><span class="p">);</span>
    <span class="n">Item</span> <span class="n">child1</span> <span class="p">=</span> <span class="n">child1Fake</span><span class="p">.</span><span class="nf">WithName</span><span class="p">(</span><span class="s">"Getting Started"</span><span class="p">);</span>
    <span class="n">Item</span> <span class="n">child2</span> <span class="p">=</span> <span class="n">child2Fake</span><span class="p">.</span><span class="nf">WithName</span><span class="p">(</span><span class="s">"Troubleshooting"</span><span class="p">);</span>

    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child1</span><span class="p">,</span> <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Getting Started"</span><span class="p">]);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">child2</span><span class="p">,</span> <span class="n">parent</span><span class="p">.</span><span class="n">Children</span><span class="p">[</span><span class="s">"Troubleshooting"</span><span class="p">]);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">HasChildren</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">child1</span><span class="p">.</span><span class="n">Parent</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">,</span> <span class="n">child2</span><span class="p">.</span><span class="n">Parent</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">,</span> <span class="n">child1</span><span class="p">.</span><span class="n">ParentID</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">ID</span><span class="p">,</span> <span class="n">child2</span><span class="p">.</span><span class="n">ParentID</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Following this approach you won’t need to introduce extension methods and implement fake item logic. Potential disadvantage is yet another alternative item management API (like in FakeDb). I’d like Sitecore to let us use default API without the necessity to jump between <code class="language-plaintext highlighter-rouge">FakeItem</code>/<code class="language-plaintext highlighter-rouge">DbItem</code> and <code class="language-plaintext highlighter-rouge">Item</code>.</p>

<p>You can find the full example <a href="https://gist.github.com/sshushliapin/b1f11556e51010fc2ac667eecfafbf05">here</a>.</p>

<h3 id="conclusion">Conclusion</h3>

<p>There is a wide list of options how to set item children in tests. You can use old good FakeDb, you can configure simple mocks per prop/method call, you can combine mocks with fake logic to impact related props or you can use existing tools like Sitecore.NSubstituteUtils. Of course, it’s up to you to choose the most suitable approach.</p>

<p>All the test samples can be found in the <a href="https://github.com/sshushliapin/SitecoreUnitTestingSamples/tree/master/SitecoreUnitTestingSamples">SitecoreUnitTestingSamples</a> GitHub repo.</p>]]></content><author><name>Serhii Shushliapin</name></author><category term="unit-testing" /><summary type="html"><![CDATA[Probably one of the most used item operations is requesting its children. FakeDb typically configures item hierarchy in the db context setup block (see using statement). Likely, for mocks that is not needed. In this post I’ll show few advanced ways to extend ItemCustomization in order to add subitems to a mocked item.]]></summary></entry><entry><title type="html">Testing content tree via mocked item axes</title><link href="/2019/12/30/testing-content-tree-via-mocked-item-axes" rel="alternate" type="text/html" title="Testing content tree via mocked item axes" /><published>2019-12-30T00:02:00+00:00</published><updated>2019-12-30T00:02:00+00:00</updated><id>/2019/12/30/testing-content-tree-via-mocked-item-axes</id><content type="html" xml:base="/2019/12/30/testing-content-tree-via-mocked-item-axes"><![CDATA[<p>In the <a href="/2019/12/25/switching-from-fakedb-to-mocks.html">previous post</a> I showed that FakeDb is not the only way of doing unit testing in Sitecore nowadays. Today I want to grab a real class with tests on FakeDb and create an alternative tests suite based on mocks and AutoFixture. You will see how to grow the test setup and will have a better chance to compare two approaches.</p>

<p>As a system under test (SUT) I took a <a href="https://github.com/Sitecore/Helix.Examples/blob/master/examples/helix-basic-unicorn/src/Feature/Navigation/website/Services/NavigationRootResolver.cs#L9">small class</a> from the <a href="https://github.com/Sitecore/Helix.Examples#welcome-to-the-sitecore-helix-examples-repository">Helix Examples</a> repo. I hope no one will blame me for that. The repo contains Sitecore code samples and this particular class looks extremely attractive from the unit testing perspective. It is quite simple, in the same time it requires some configuration. In addition, this class is covered with FakeDb tests which gives us an opportunity to compare two testing techniques.</p>

<h3 id="system-under-test-navigationrootresolver">System Under Test: NavigationRootResolver</h3>

<p>At the time of this writing, the NavigationRootResolver looks like the following:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">NavigationRootResolver</span> <span class="p">:</span> <span class="n">INavigationRootResolver</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="n">Item</span> <span class="nf">GetNavigationRoot</span><span class="p">(</span><span class="n">Item</span> <span class="n">contextItem</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">contextItem</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="k">null</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">contextItem</span><span class="p">.</span><span class="nf">DescendsFrom</span><span class="p">(</span><span class="n">Templates</span><span class="p">.</span><span class="n">NavigationRoot</span><span class="p">.</span><span class="n">Id</span><span class="p">)</span>
            <span class="p">?</span> <span class="n">contextItem</span>
            <span class="p">:</span> <span class="n">contextItem</span><span class="p">.</span><span class="n">Axes</span><span class="p">.</span><span class="nf">GetAncestors</span><span class="p">().</span><span class="nf">LastOrDefault</span><span class="p">(</span><span class="n">x</span> <span class="p">=&gt;</span>
                <span class="n">x</span><span class="p">.</span><span class="nf">DescendsFrom</span><span class="p">(</span><span class="n">Templates</span><span class="p">.</span><span class="n">NavigationRoot</span><span class="p">.</span><span class="n">Id</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Branches to test:</p>

<ol>
  <li>If <code class="language-plaintext highlighter-rouge">contextItem</code> is null, return null</li>
  <li>If <code class="language-plaintext highlighter-rouge">contextItem</code> is based on NavigationRoot template, return context item</li>
  <li>If not, return last ancestor based on the navigation template</li>
</ol>

<p>Scenario 3 is a bit tricky. It requires the last ancestor of a given template. It is very easy to overlook this scenario and I’ll get back to this later. Now let’s write some tests.</p>

<h3 id="tests">Tests</h3>

<p>The first case is trivial and does not require any testing techniques. We can even use default AutoFixture <code class="language-plaintext highlighter-rouge">[AutoData]</code> attribute since the only thing we need is an instance of a class without parameters:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">AutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetNavigationRootWithNullReturnsNull</span><span class="p">(</span>
    <span class="n">NavigationRootResolver</span> <span class="n">sut</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">actual</span> <span class="p">=</span> <span class="n">sut</span><span class="p">.</span><span class="nf">GetNavigationRoot</span><span class="p">(</span><span class="k">null</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Null</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>To solve the second case we should use the <code class="language-plaintext highlighter-rouge">[DefaultAutoData]</code> attribute <a href="https://gist.github.com/sshushliapin/f7937ab589cc4588fc7515cbbfbc82de#file-sitecoreunittestingsamples-firstmock-L34">created earlier</a>. Just an empty item without any fields or template configuration works well here. We only need to configure the <code class="language-plaintext highlighter-rouge">DescendsFrom</code> method and it is easy to do that since our <code class="language-plaintext highlighter-rouge">item</code> is a mock:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetNavigationRootReturnsItemDescendantFromRootTemplate</span><span class="p">(</span>
    <span class="n">NavigationRootResolver</span> <span class="n">sut</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">expected</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">expected</span><span class="p">.</span><span class="nf">DescendsFrom</span><span class="p">(</span><span class="n">NavigationRootResolver</span><span class="p">.</span><span class="n">NavRootTemplateId</span><span class="p">).</span><span class="nf">Returns</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">actual</span> <span class="p">=</span> <span class="n">sut</span><span class="p">.</span><span class="nf">GetNavigationRoot</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">actual</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>So far, so good. We’re getting closer to the most interesting part. We need to receive all the item ancestors and choose the last of them which is descendant from Navigation Root template. But first let’s take a look on a FakeDb test first.</p>

<h3 id="content-tree-test-with-fakedb">Content tree test with FakeDb</h3>

<p>FakeDb is all about the content. That’s probably the most powerful selling point of the entire framework. You see the content, you execute your API against this content, and if it works, it will (most likely) work in a real Sitecore environment. The code below creates a navigation root template, then another template based on the root and after that three levels of the nested items.</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">homeTemplate</span> <span class="p">=</span> <span class="n">ID</span><span class="p">.</span><span class="n">NewID</span><span class="p">;</span>
<span class="n">_db</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Db</span>
<span class="p">{</span>
    <span class="k">new</span> <span class="nf">DbTemplate</span><span class="p">(</span><span class="n">Templates</span><span class="p">.</span><span class="n">NavigationRoot</span><span class="p">.</span><span class="n">Id</span><span class="p">),</span>
    <span class="k">new</span> <span class="nf">DbTemplate</span><span class="p">(</span><span class="n">homeTemplate</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">BaseIDs</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">Templates</span><span class="p">.</span><span class="n">NavigationRoot</span><span class="p">.</span><span class="n">Id</span> <span class="p">}</span>
    <span class="p">},</span>
    <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Home"</span><span class="p">,</span> <span class="n">ID</span><span class="p">.</span><span class="n">NewID</span><span class="p">,</span> <span class="n">homeTemplate</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Child"</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Grandchild"</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">};</span>
<span class="n">_rootItem</span> <span class="p">=</span> <span class="n">_db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/Home"</span><span class="p">);</span>
</code></pre></div></div>

<p>Now, having such a content tree, it’s easy to test all the scenarios (I’ll show only the last one, you can find all the rest in the <a href="https://github.com/Sitecore/Helix.Examples/blob/master/examples/helix-basic-unicorn/src/Feature/Navigation/tests/NavigationRootResolverTests.cs">Helix Examples</a>):</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Fact</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">ResolvesWhenContextItemIsGrandchild</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">contextItem</span> <span class="p">=</span> <span class="n">_db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/Home/Child/Grandchild"</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">rootResolver</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">NavigationRootResolver</span><span class="p">();</span>
    <span class="kt">var</span> <span class="n">resolvedItem</span> <span class="p">=</span> <span class="n">rootResolver</span><span class="p">.</span><span class="nf">GetNavigationRoot</span><span class="p">(</span><span class="n">contextItem</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="n">_rootItem</span><span class="p">.</span><span class="n">ID</span><span class="p">,</span> <span class="n">resolvedItem</span><span class="p">.</span><span class="n">ID</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="what-about-mocks">What about mocks</h3>

<p>With mocks there is no content ‘visualized’ in code. You cannot just run your API against fast in-memory database and see if it works. You have to <em>know</em> which mocked methods to configure and call. The reward is a smaller size of the Arrange block and avoiding Sitecore internals:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetNavigationRootReturnsLastAncestorDescendantFromRootTemplate</span><span class="p">(</span>
    <span class="n">NavigationRootResolver</span> <span class="n">sut</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">contextItem</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">ancestor1</span><span class="p">,</span>
    <span class="n">Item</span> <span class="n">expected</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">ancestor1</span><span class="p">.</span><span class="nf">DescendsFrom</span><span class="p">(</span><span class="n">NavigationRootResolver</span><span class="p">.</span><span class="n">NavRootTemplateId</span><span class="p">).</span><span class="nf">Returns</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
    <span class="n">expected</span><span class="p">.</span><span class="nf">DescendsFrom</span><span class="p">(</span><span class="n">NavigationRootResolver</span><span class="p">.</span><span class="n">NavRootTemplateId</span><span class="p">).</span><span class="nf">Returns</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
    <span class="n">contextItem</span><span class="p">.</span><span class="n">Axes</span><span class="p">.</span><span class="nf">GetAncestors</span><span class="p">().</span><span class="nf">Returns</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="n">ancestor1</span><span class="p">,</span> <span class="n">expected</span> <span class="p">});</span>

    <span class="kt">var</span> <span class="n">actual</span> <span class="p">=</span> <span class="n">sut</span><span class="p">.</span><span class="nf">GetNavigationRoot</span><span class="p">(</span><span class="n">contextItem</span><span class="p">);</span>

    <span class="n">Assert</span><span class="p">.</span><span class="nf">Same</span><span class="p">(</span><span class="n">expected</span><span class="p">,</span> <span class="n">actual</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Note that nobody cares about template hierarchy here. Mocking <code class="language-plaintext highlighter-rouge">DescendsFrom</code> and <code class="language-plaintext highlighter-rouge">GetAncestors</code> methods fully covers the testing scenario.</p>

<h3 id="extending-item-customization">Extending Item Customization</h3>

<p>Finally, we’ve got some good test but it’s failing. The issue is in the <code class="language-plaintext highlighter-rouge">contextItem.Axes.GetAncestors()</code> call which throws Null Reference Exception. That is expected since in the <code class="language-plaintext highlighter-rouge">ItemCustomization</code> we’ve just created an empty item mock and have not configured any fields. Let’s do that now:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">item</span><span class="p">.</span><span class="n">Axes</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">ItemAxes</span><span class="p">&gt;(</span><span class="n">item</span><span class="p">));</span>
</code></pre></div></div>

<p>I’ve also simplified a bit the item creation customization. Instead of calling NSubstitute to create <code class="language-plaintext highlighter-rouge">ID</code>, <code class="language-plaintext highlighter-rouge">ItemData</code> and <code class="language-plaintext highlighter-rouge">Database</code> I’m relying on AutoFixture now. That is the updated ItemCustomization version:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">ItemCustomization</span> <span class="p">:</span> <span class="n">ICustomization</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">Customize</span><span class="p">(</span><span class="n">IFixture</span> <span class="n">fixture</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">fixture</span><span class="p">.</span><span class="n">Customize</span><span class="p">&lt;</span><span class="n">Item</span><span class="p">&gt;(</span><span class="n">x</span> <span class="p">=&gt;</span>
            <span class="n">x</span><span class="p">.</span><span class="n">FromFactory</span><span class="p">&lt;</span><span class="n">ID</span><span class="p">,</span> <span class="n">ItemData</span><span class="p">,</span> <span class="n">Database</span><span class="p">&gt;(</span><span class="n">CreateItem</span><span class="p">)</span>
                <span class="p">.</span><span class="nf">OmitAutoProperties</span><span class="p">());</span>
    <span class="p">}</span>

    <span class="k">private</span> <span class="k">static</span> <span class="n">Item</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">ID</span> <span class="n">id</span><span class="p">,</span> <span class="n">ItemData</span> <span class="n">itemData</span><span class="p">,</span> <span class="n">Database</span> <span class="n">database</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">item</span> <span class="p">=</span> <span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">Item</span><span class="p">&gt;(</span><span class="n">id</span><span class="p">,</span> <span class="n">itemData</span><span class="p">,</span> <span class="n">database</span><span class="p">);</span>
        <span class="n">item</span><span class="p">.</span><span class="n">Axes</span><span class="p">.</span><span class="nf">Returns</span><span class="p">(</span><span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">ItemAxes</span><span class="p">&gt;(</span><span class="n">item</span><span class="p">));</span>

        <span class="k">return</span> <span class="n">item</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Please note that the ItemCustomization above is not a new class. It is a new extended version of the customization created before. Typically, it grows altogether with the unit testing codebase allowing to test new and new scenarios. If we leave it aside, the created tests are <a href="https://gist.github.com/sshushliapin/2469790ccec20fc21a993b3fab122d15">three times smaller</a> comparing to the <a href="https://github.com/Sitecore/Helix.Examples/blob/master/examples/helix-basic-unicorn/src/Feature/Navigation/tests/NavigationRootResolverTests.cs">old fashion FakeDb tests</a>.</p>

<h3 id="missing-test-case">Missing test case</h3>

<p>Earlier in this post I mentioned that the scenario 3 is a bit tricky. And that is why. Please take a look on this content setup:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Home"</span><span class="p">,</span> <span class="n">ID</span><span class="p">.</span><span class="n">NewID</span><span class="p">,</span> <span class="n">homeTemplate</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Child"</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Grandchild"</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You see it? Only Home item is based on the Root template. This content <em>looks</em> correct. That’s how one would configure it in the Content Editor. And that is why it is a trap of a Real Content. In <code class="language-plaintext highlighter-rouge">NavigationRootResolver</code> the <code class="language-plaintext highlighter-rouge">contextItem.Axes.GetAncestors().LastOrDefault(...);</code> call is never properly validated because there is only one item of this template available. Method can be replaced with the <code class="language-plaintext highlighter-rouge">.FirstOfDefault</code> and the test will still pass returning false positive result.</p>

<p>Of course this scenario can be easily fixed no matter if you go with FakeDb or mocks. My point is that starting from a real content and positive scenario increases chances to overlook important test cases.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Both approaches are sufficient to test scenario with nested items and template hierarchy. With FakeDb you have a chance to literally <em>see</em> your content but should beware Real Content trap. With mocks you can configure only bare minimum of calls to pass test case and, as a result, have smaller tests which are easier to maintain.</p>]]></content><author><name>Serhii Shushliapin</name></author><category term="unit-testing" /><summary type="html"><![CDATA[In the previous post I showed that FakeDb is not the only way of doing unit testing in Sitecore nowadays. Today I want to grab a real class with tests on FakeDb and create an alternative tests suite based on mocks and AutoFixture. You will see how to grow the test setup and will have a better chance to compare two approaches.]]></summary></entry><entry><title type="html">Switching from FakeDb to mocks</title><link href="/2019/12/25/switching-from-fakedb-to-mocks" rel="alternate" type="text/html" title="Switching from FakeDb to mocks" /><published>2019-12-25T10:07:00+00:00</published><updated>2019-12-25T10:07:00+00:00</updated><id>/2019/12/25/switching-from-fakedb-to-mocks</id><content type="html" xml:base="/2019/12/25/switching-from-fakedb-to-mocks"><![CDATA[<p>Historically, Sitecore was not a unit test friendly platform. The API consisted of static managers and testing was quite cumbersome. There were different attempts to address that starting from ‘unit testing’ via <a href="https://www.codeflood.net/testrunner/">web runners</a>, using commercial tools that could ‘mock’ statics (like <a href="https://docs.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2019">Microsoft Fakes</a>) or just relying on expensive integration testing.</p>

<h3 id="in-memory-database">In-memory database</h3>

<p><a href="https://github.com/sshushliapin/Sitecore.FakeDb">FakeDb</a> provided a mechanism to substitute database calls with fake in-memory data. It also provided an alternative API to set the content with minimal amount of code. It worked out, but everything has a price. First of all, till some point FakeDb has to run <em>real</em> Sitecore code. The most obvious (and annoying) indication of that is the <a href="https://github.com/sshushliapin/Sitecore.FakeDb/wiki/Installation#applying-the-license-file">necessity of using license file</a> and <a href="https://github.com/Sitecore/Habitat/pull/433/files">additional cofiguration steps</a>.</p>

<p>Another potential issue is a risk of breaking and/or behavior changes in the Platform. FakeDb version 1 managed to cover wide range of Sitecore versions <a href="https://github.com/sshushliapin/Sitecore.FakeDb/blob/v1.7.4/version.props#L7-L8">7.2, 8.0, 8.1, 8.2</a> with numerous updates. Version 2 works with <a href="https://github.com/sshushliapin/Sitecore.FakeDb/blob/v2.0.1/version.props#L7">9.1 and 9.2</a> and version 3 had to <a href="https://github.com/sshushliapin/Sitecore.FakeDb/pull/213">overcome list of breaking changes</a> to be compatible with 9.3. We cannot predict what may change in platform in future and how it can impact the tool.</p>

<p>FakeDb <a href="https://github.com/sshushliapin/Sitecore.FakeDb/blob/master/test/Sitecore.FakeDb.Tests/App.config#L8">cannot run test in parallel</a>. Probably, not the worst limitation for a tool which is able to run hundreds of tests in seconds, but anyway, just for you to know.</p>

<h3 id="an-alternative">An alternative</h3>

<p>As you see, most of the issues appear because FakeDb calls Sitecore internals. Likely, starting from 8.2 Sitecore API has got abstractions which is a significant reason to reconsider existing testing approaches. No license required, no Sitecore internal calls, no parallel execution limitation. As soon as we can mock Sitecore classes, we’re good to go.</p>

<p>It looks extremely attractive to me and that’s why I’d like to start a series of posts describing how to mock different pieces of Sitecore. There are <a href="https://github.com/smarchenko/SitecoreDI.NSubstitute.Helper">some tools</a> <a href="https://github.com/dsolovay/AutoSitecore">doing that</a> but let’s start from the beginning.</p>

<h3 id="fakedb-style-of-unit-testing">FakeDb style of unit testing</h3>

<p>In FakeDb, a typical unit test looks like <a href="https://github.com/sshushliapin/Sitecore.FakeDb#sitecore-fakedb">this</a>:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Fact</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">HowToCreateSimpleItem</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">using</span> <span class="p">(</span><span class="kt">var</span> <span class="n">db</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Db</span>
    <span class="p">{</span>
        <span class="k">new</span> <span class="nf">DbItem</span><span class="p">(</span><span class="s">"Home"</span><span class="p">)</span> <span class="p">{</span> <span class="p">{</span> <span class="s">"Title"</span><span class="p">,</span> <span class="s">"Welcome!"</span> <span class="p">}</span> <span class="p">}</span>
    <span class="p">})</span>
    <span class="p">{</span>
        <span class="n">Sitecore</span><span class="p">.</span><span class="n">Data</span><span class="p">.</span><span class="n">Items</span><span class="p">.</span><span class="n">Item</span> <span class="n">home</span> <span class="p">=</span> <span class="n">db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/home"</span><span class="p">);</span>
        <span class="n">Xunit</span><span class="p">.</span><span class="n">Assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">,</span> <span class="n">home</span><span class="p">[</span><span class="s">"Title"</span><span class="p">]);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The few lines of code above do the following:</p>

<ul>
  <li>create an auto-generated template with <code class="language-plaintext highlighter-rouge">Title</code> field</li>
  <li>create an item based on this template</li>
  <li>store the item under specific location so that it can be retrieved by path</li>
  <li>set <code class="language-plaintext highlighter-rouge">Title</code> field value</li>
</ul>

<p>Looks straightforward and familiar. Let’s see how this test can be rewritten with mocks.</p>

<h3 id="mocking-sitecore-with-autofixture">Mocking Sitecore with AutoFixture</h3>

<p>Same properties but configured in the different way:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetItem</span><span class="p">(</span><span class="n">Database</span> <span class="n">db</span><span class="p">,</span> <span class="n">Item</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">item</span><span class="p">[</span><span class="s">"Title"</span><span class="p">].</span><span class="nf">Returns</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">);</span>
    <span class="n">db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/home"</span><span class="p">).</span><span class="nf">Returns</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">,</span> <span class="n">item</span><span class="p">[</span><span class="s">"Title"</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As you could notice, there is no db context. You’ve got item and database variables and you’re free to configure them the way you need. There is a couple of steps you need to perform to make this code working, but the good news are that you need to do that <em>once</em> when starting a new project. Let’s set up a solution first.</p>

<h2 id="toolset">Toolset</h2>

<p>In my posts I’ll use <a href="https://xunit.net/">xUnit</a>, <a href="https://nsubstitute.github.io/">NSubstitute</a> and <a href="https://github.com/AutoFixture/AutoFixture">AutoFixture</a>. <a href="https://nunit.org/">NUnit</a>, and <a href="https://github.com/Moq/moq4/wiki/Quickstart">Moq</a> would work as well, that’s just a matter of preference. But AutoFixture (AF) - that what makes the difference. This tool can help significantly if used the right way. If you not familiar with AF, please refer to the <a href="https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet">Cheat Sheet</a> page.</p>

<p>All we need is a class library referencing the following NuGet packages:</p>

<ul>
  <li><a href="https://www.nuget.org/packages/AutoFixture">AutoFixture</a></li>
  <li><a href="https://www.nuget.org/packages/AutoFixture.xUnit2">AutoFixture.xUnit2</a></li>
  <li><a href="https://www.nuget.org/packages/NSubstitute">NSubstitute</a></li>
  <li><a href="https://www.nuget.org/packages/xunit">xunit</a></li>
  <li><a href="https://www.nuget.org/packages/xunit.runner.visualstudio">xunit.runner.visualstudio</a> (optional)</li>
</ul>

<p>And the following Sitecore packages:</p>

<ul>
  <li><a href="https://sitecore.myget.org/feed/sc-packages/package/nuget/Sitecore.Kernel">Sitecore.Kernel</a></li>
  <li><a href="https://sitecore.myget.org/feed/sc-packages/package/nuget/Sitecore.Nexus">Sitecore.Nexus</a></li>
  <li><a href="https://sitecore.myget.org/feed/sc-packages/package/nuget/Sitecore.Nexus.Licensing/2.0.6">Sitecore.Nexus.Licensing</a> (please note that version <code class="language-plaintext highlighter-rouge">2.0.6</code> is <em>newer</em> than <code class="language-plaintext highlighter-rouge">9.0.180604</code>)</li>
</ul>

<p>Now, when we’re done with the project setup let’s look on the test in details.</p>

<h3 id="setting-up-autofixture-database">Setting up AutoFixture: Database</h3>

<p>AutoFixture is good at creating primitive and simple types but it requires some help when dealing with abstractions or circular dependencies. We’ll need to teach it how to instantiate <code class="language-plaintext highlighter-rouge">Database</code> and <code class="language-plaintext highlighter-rouge">Item</code> which contain both.</p>

<p>If we try to create a database using native AF <code class="language-plaintext highlighter-rouge">[AutoData]</code> attribute, the test will fail:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">AutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">CreateDatabase</span><span class="p">(</span><span class="n">Database</span> <span class="n">database</span><span class="p">)</span> <span class="c1">// fails here</span>
<span class="p">{</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">NotNull</span><span class="p">(</span><span class="n">database</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// Error:</span>
<span class="c1">// AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to create</span>
<span class="c1">// an instance from Sitecore.Data.Database because creation unexpectedly failed</span>
<span class="c1">// with exception. Please refer to the inner exception to investigate the root</span>
<span class="c1">// cause of the failure.</span>
</code></pre></div></div>

<p>AutoFixture did not manage to create an instance of abstract database type but it provides a mechanism of <a href="https://blog.ploeh.dk/2011/03/18/EncapsulatingAutoFixtureCustomizations/">customizations</a> to handle such scenarios. All we need is to create a class that will instantiate a database mock:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">DatabaseCustomization</span> <span class="p">:</span> <span class="n">AutoFixture</span><span class="p">.</span><span class="n">ICustomization</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">Customize</span><span class="p">(</span><span class="n">IFixture</span> <span class="n">fixture</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">fixture</span><span class="p">.</span><span class="n">Customize</span><span class="p">&lt;</span><span class="n">Database</span><span class="p">&gt;(</span><span class="n">x</span> <span class="p">=&gt;</span>
            <span class="n">x</span><span class="p">.</span><span class="nf">FromFactory</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">Database</span><span class="p">&gt;())</span>
                <span class="p">.</span><span class="nf">OmitAutoProperties</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now we need to apply the customization to the test <em>fixture</em> so that we receive a mocked database instance as a test parameter:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">DefaultAutoDataAttribute</span> <span class="p">:</span> <span class="n">AutoDataAttribute</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="nf">DefaultAutoDataAttribute</span><span class="p">()</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="nf">Fixture</span><span class="p">().</span><span class="nf">Customize</span><span class="p">(</span><span class="k">new</span> <span class="nf">DatabaseCustomization</span><span class="p">()))</span>
    <span class="p">{</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>After that we need to replace AF <code class="language-plaintext highlighter-rouge">[AutoData]</code> with our new <code class="language-plaintext highlighter-rouge">[DefaultAutoData]</code> attribute and the test is now green. We’ve got a mocked instance of a database:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">CreateDatabase</span><span class="p">(</span><span class="n">Database</span> <span class="n">database</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">NotNull</span><span class="p">(</span><span class="n">database</span><span class="p">);</span> <span class="c1">// pass</span>
<span class="p">}</span>
</code></pre></div></div>

<p>From now on, for all the tests that requires Sitecore classes, the <code class="language-plaintext highlighter-rouge">[DefaultAutoData]</code> attribute should be used.</p>

<h3 id="setting-up-autofixture-item">Setting up AutoFixture: Item</h3>

<p>Now when we can instatiate <code class="language-plaintext highlighter-rouge">Database</code> we can move to the next step and try to create an item. Again, it fails so we need to teach AF how to do that.</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">Item</span> <span class="n">item</span><span class="p">)</span> <span class="c1">// fails here</span>
<span class="p">{</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">NotNull</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// Error:</span>
<span class="c1">// AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to create an instance from Sitecore.Data.Items.Item.</span>
<span class="c1">// ...</span>
<span class="c1">// Inner exception messages:</span>
<span class="c1">// System.TypeInitializationException: The type initializer for 'Sitecore.SecurityModel.License.LicenseManager' threw an exception.</span>
</code></pre></div></div>

<p>License Manager in the stack trace? It means that we’re running <em>internal</em> Sitecore code. To make robust tests we should avoid that and mock the item. One more customization is needed.</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">ItemCustomization</span> <span class="p">:</span> <span class="n">ICustomization</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">Customize</span><span class="p">(</span><span class="n">IFixture</span> <span class="n">fixture</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">fixture</span><span class="p">.</span><span class="n">Customize</span><span class="p">&lt;</span><span class="n">Item</span><span class="p">&gt;(</span><span class="n">x</span> <span class="p">=&gt;</span>
            <span class="n">x</span><span class="p">.</span><span class="nf">FromFactory</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">fixture</span><span class="p">))</span>
                <span class="p">.</span><span class="nf">OmitAutoProperties</span><span class="p">()</span>
        <span class="p">);</span>
    <span class="p">}</span>

    <span class="k">private</span> <span class="k">static</span> <span class="n">Item</span> <span class="nf">CreateItem</span><span class="p">(</span><span class="n">ISpecimenBuilder</span> <span class="n">fixture</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">var</span> <span class="n">item</span> <span class="p">=</span> <span class="n">Substitute</span><span class="p">.</span><span class="n">For</span><span class="p">&lt;</span><span class="n">Item</span><span class="p">&gt;(</span>
            <span class="n">fixture</span><span class="p">.</span><span class="n">Create</span><span class="p">&lt;</span><span class="n">ID</span><span class="p">&gt;(),</span>
            <span class="n">fixture</span><span class="p">.</span><span class="n">Create</span><span class="p">&lt;</span><span class="n">ItemData</span><span class="p">&gt;(),</span>
            <span class="n">fixture</span><span class="p">.</span><span class="n">Create</span><span class="p">&lt;</span><span class="n">Database</span><span class="p">&gt;());</span>

        <span class="k">return</span> <span class="n">item</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Please note how do we use <code class="language-plaintext highlighter-rouge">fixture</code> to create database. We can do that now since we’ve already created customization that is able to create it.</p>

<p>Now, extending the <code class="language-plaintext highlighter-rouge">DefaulAutoData</code> attribute with the new customization.</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">internal</span> <span class="k">class</span> <span class="nc">DefaultAutoDataAttribute</span> <span class="p">:</span> <span class="n">AutoDataAttribute</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="nf">DefaultAutoDataAttribute</span><span class="p">()</span>
        <span class="p">:</span> <span class="k">base</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="k">new</span> <span class="nf">Fixture</span><span class="p">()</span>
            <span class="p">.</span><span class="nf">Customize</span><span class="p">(</span><span class="k">new</span> <span class="nf">DatabaseCustomization</span><span class="p">())</span>
            <span class="p">.</span><span class="nf">Customize</span><span class="p">(</span><span class="k">new</span> <span class="nf">ItemCustomization</span><span class="p">()))</span>
    <span class="p">{</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And finally, the test with mocked item is green! I’ll paste it once again here:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">,</span> <span class="n">DefaultAutoData</span><span class="p">]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">GetItem</span><span class="p">(</span><span class="n">Database</span> <span class="n">db</span><span class="p">,</span> <span class="n">Item</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">item</span><span class="p">[</span><span class="s">"Title"</span><span class="p">].</span><span class="nf">Returns</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">);</span>
    <span class="n">db</span><span class="p">.</span><span class="nf">GetItem</span><span class="p">(</span><span class="s">"/sitecore/content/home"</span><span class="p">).</span><span class="nf">Returns</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">,</span> <span class="n">item</span><span class="p">[</span><span class="s">"Title"</span><span class="p">]);</span> <span class="c1">// pass</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Very simple, very straightforward, without limitations FakeDb tests have. If that is not a replacement of FakeDb, that is, at least, a good alternative to be aware about. The full code sample can be found <a href="https://gist.github.com/sshushliapin/f7937ab589cc4588fc7515cbbfbc82de">here</a>. In the next posts I’ll show ho to extend the test set up and configure other item properties. Stay tuned!</p>]]></content><author><name>Serhii Shushliapin</name></author><category term="unit-testing" /><summary type="html"><![CDATA[Historically, Sitecore was not a unit test friendly platform. The API consisted of static managers and testing was quite cumbersome. There were different attempts to address that starting from ‘unit testing’ via web runners, using commercial tools that could ‘mock’ statics (like Microsoft Fakes) or just relying on expensive integration testing.]]></summary></entry></feed>