<?xml version="1.0" encoding="UTF-8"?><rss 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" version="2.0"><channel><title><![CDATA[Erik Medina]]></title><description><![CDATA[Hi!

I'm Erik, a software developer specialising in Android applications. 

I was born in Peru but raised in Spain. Now living in the UK long enough to love que]]></description><link>https://erikmedina.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 04:43:18 GMT</lastBuildDate><atom:link href="https://erikmedina.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building an artificial back stack with the Android Navigation component]]></title><description><![CDATA[Context
Backwards navigation with Navigation Component isn't a mystery, is it? We don't have to do anything, we have it for free.
But, what if you want to navigate straight to a specific destination? And be able to navigate back to the start destinat...]]></description><link>https://erikmedina.dev/building-an-artificial-back-stack-with-the-android-navigation-component</link><guid isPermaLink="true">https://erikmedina.dev/building-an-artificial-back-stack-with-the-android-navigation-component</guid><category><![CDATA[Android]]></category><category><![CDATA[android development]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[navigation]]></category><category><![CDATA[android app development]]></category><dc:creator><![CDATA[Erik Medina]]></dc:creator><pubDate>Sun, 26 Dec 2021 16:53:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1640537418044/t7hAxLvmT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-context">Context</h2>
<p>Backwards navigation with Navigation Component isn't a mystery, is it? We don't have to do anything, we have it for free.</p>
<p>But, what if you want to navigate straight to a specific destination? And be able to navigate back to the <em>start destination</em>? Like if you had navigated manually to that specific destination.</p>
<p>I expected that the backwards navigation continues working but it doesn't. And this is the reason that this article exists.</p>
<blockquote>
<p><strong>Note</strong>: <a target="_blank" href="https://developer.android.com/guide/navigation/navigation-principles#deep-link">deep linking</a> provides this behaviour. It simulates manual navigation and creates a synthetic back stack.</p>
</blockquote>
<h2 id="heading-understanding-the-back-stack">Understanding the  back stack</h2>
<p>The first thing is to understand what the back stack is and how it works with the Navigation component. The back stack is a <a target="_blank" href="https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29">LIFO stack</a> that stores the activity and its fragments. The last fragment pushed onto the back stack will be the first fragment popped off the stack when we hit the back button.</p>
<p>For example, if we have the following navigation:</p>
<p><strong>Fragment A -&gt; Fragment B -&gt; Fragment C</strong></p>
<p>Its back stack will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640264125412/OzRTVq0uK.png" alt="Navigation Component.drawio.png" /></p>
<p>If we hit the back button, the fragment on the top is popped off the stack and now <strong>Fragment B</strong> is in the foreground:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640432303538/O49pu5i5l.png" alt="image.png" /></p>
<p>Hit the back button again and <strong>Fragment B</strong> is popped off the stack:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640432342329/FBhdGv6jOj.png" alt="image.png" /></p>
<p>Finally, if we hit the back button one more time, <strong>Fragment A</strong> and the activity are popped off the stack and we exit the app:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640432504434/6wHzc4WU9.png" alt="image.png" /></p>
<p>This backwards navigation behaviour comes for free, we don't have to do anything.</p>
<h2 id="heading-problem">Problem</h2>
<p>The described behaviour works as long as we navigate manually to a destination. Yet, what if we want to navigate to a specific destination skipping destinations in between? And be able to navigate back to the <em>start destination</em>?</p>
<p>You can think of a sign-up flow for example. You may want to let the user leave the flow at any point. And allow him to rejoin the flow at the last point he left (and don't lose a user because of a long sign-up process).</p>
<p>In this case, the backwards navigation isn't what we expect. If we navigate straight to <strong>Fragment C</strong> and hit the back button, we won't see <strong>Fragment B</strong>. We'll see <strong>Fragment A</strong>. What is happening is that <strong>Fragment B</strong> wasn't pushed onto the back stack because we never navigated to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640343721839/Bpidq-6pA.png" alt="Navigation Component.drawio (5).png" /></p>
<h2 id="heading-solution">Solution</h2>
<p>To amend this problem, the solution I've found is that we have to build the back navigation ourselves.</p>
<h2 id="heading-show-me-the-code">Show me the code</h2>
<p>You can find the code <a target="_blank" href="https://github.com/ErikMedina/NavigationComponent/tree/artificial-back-stack">here</a> (<code>artificial-back-stack</code> branch).</p>
<p>The aim is to have a navigation graph where all the destinations are connected forwards and backwards:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640346305799/WzQorMEOk.png" alt="NavGraph" /></p>
<p>For this example, I'll have <code>HomeFragment</code> as the <em>start destination</em>; and <code>FirstFragment</code>, <code>SecondFragment</code> and, <code>ThirdFragment</code> as destinations.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="d530c66fd981dc29c969e606d677531e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ErikMedina/d530c66fd981dc29c969e606d677531e" class="embed-card">https://gist.github.com/ErikMedina/d530c66fd981dc29c969e606d677531e</a></div><p>The graph will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640284988306/l36128Lip.png" alt="image.png" /></p>
<p>Once we have the forwards navigation, we have to build the backwards navigation. Thus, when we navigate straight to a destination, we're still able to navigate back to the <em>start destination</em>. For that, we have to add the actions for the backwards navigation:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="72f97472659641903bf8d4aa56d3dddf"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ErikMedina/72f97472659641903bf8d4aa56d3dddf" class="embed-card">https://gist.github.com/ErikMedina/72f97472659641903bf8d4aa56d3dddf</a></div><p>We also have to provide  <a target="_blank" href="https://developer.android.com/guide/navigation/navigation-custom-back">custom back navigation</a> to our fragments and specify the action. For example, this is how we'd provide custom back navigation to <code>FirstFragment</code>:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="d6623364f2fca109ce86bc4f1ed45da5"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ErikMedina/d6623364f2fca109ce86bc4f1ed45da5" class="embed-card">https://gist.github.com/ErikMedina/d6623364f2fca109ce86bc4f1ed45da5</a></div><p>Everything seems to work fine. We can navigate through the navigation graph forwards and backwards. However, when we navigate back to the <code>HomeFragment</code>, we'll notice a bug. We enter a loop between the <code>HomeFragment</code> and the <code>FirstFragment</code> and can't exit the app:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/rBA6xQQvuZQ">https://youtu.be/rBA6xQQvuZQ</a></div>
<h3 id="heading-what-is-happening">What is happening?</h3>
<p>Let's analyse the back stack to understand what is happening. The back stack when we launch the app:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640353497452/ktHLFSNKW.png" alt="image.png" /></p>
<p>We navigate to the <code>FirstFragment</code> and then to the <code>SecondFragment</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640380155584/QWN4dqbHs.png" alt="image.png" /></p>
<p>When we hit the back button, because of the <code>action_secondFragment_to_firstFragment</code> action, a new destination (<code>FirstFragment</code>) is <strong>added</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640380273885/xdQx2wMLd.png" alt="image.png" /></p>
<p>Hit the back button again and, because of the <code>action_firstFragment_to_homeFragment</code> action, a new <code>HomeFragment</code> is added:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640380497938/MIZ20ia7O.png" alt="image.png" /></p>
<p>Back button again and the <code>HomeFragment</code> is popped off the stack (<code>FirstFragment</code> is visible again). Hit back again and a new <code>HomeFragment</code> is added, and so on:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640437537176/StJwYDmOn.png" alt="image.png" /></p>
<h3 id="heading-how-to-fix-the-loop-bug">How to fix the loop bug</h3>
<p>We have to specify the <code>app:popUpTo</code> attribute in the <code>action_firstFragment_to_homeFragment</code> action. By including <code>app:popUpTo="@id/homeFragment"</code>, we're telling the navigation graph that all the destinations are popped off the stack until reaching the specified destination (<code>HomeFragment</code>). With this attribute, we've fixed the loop bug.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="f8b0a5d1d4b09e997907c80733f34c7d"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ErikMedina/f8b0a5d1d4b09e997907c80733f34c7d" class="embed-card">https://gist.github.com/ErikMedina/f8b0a5d1d4b09e997907c80733f34c7d</a></div><p>However, there is a new bug. We need to hit the back button twice when we're in the <code>HomeFragment</code> to exit the app:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/L7B98xyQIxU">https://youtu.be/L7B98xyQIxU</a></div>
<p>Let's analyse the back stack again to understand why this new bug is
happening. The back stack when we navigate to the <code>FirstFragment</code> and then to the <code>SecondFragment</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640381587035/DQiLSk-nh.png" alt="image.png" /></p>
<p>Let's start hitting the back button, a new <code>FirstFragment</code> is pushed onto the back stack:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640381756129/5Z5RYo4PX.png" alt="image.png" /></p>
<p>Because of <code>app:popUpTo="@id/homeFragment"</code>, when we hit the back button again, all the fragments are popped off the stack until reaching the destination <code>HomeFragment</code>. And a new <code>HomeFragment</code> is pushed onto the back stack:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640382186745/fSBsCjOFt.png" alt="image.png" /></p>
<p>Now we have two <code>HomeFragment</code> instances and this is the reason why we need to hit the back button twice to exit the app.</p>
<h3 id="heading-how-to-fix-this-new-bug">How to fix this new bug</h3>
<p>The <code>app:popUpToInclusive</code> attribute fixes the bug:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="c4c8a55996faa5fa4d0976c4ad9c9f2c"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ErikMedina/c4c8a55996faa5fa4d0976c4ad9c9f2c" class="embed-card">https://gist.github.com/ErikMedina/c4c8a55996faa5fa4d0976c4ad9c9f2c</a></div><p>This attribute pops the target off the stack as well:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640382841297/LP9lf7yuo.png" alt="image.png" /></p>
<p>Now we only have one <code>HomeFragment</code> in the back stack and hitting the back button once will exit the app:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/94z1Eihb7Mg">https://youtu.be/94z1Eihb7Mg</a></div>
<p>You can learn more about <code>app:popUpTo</code> and <code>app:popUpToInclusive</code> <a target="_blank" href="https://developer.android.com/codelabs/basic-android-kotlin-training-navigation-backstack#3">here</a> (skip to the <em>Pop additional destinations off the back stack</em> section).</p>
<h2 id="heading-thats-all">That's all</h2>
<p>I don't know if there is a better way of achieving this. I couldn't find anything that solves this problem. After investigation, this is the solution I came up with.</p>
]]></content:encoded></item><item><title><![CDATA[Finding a bug when you have no idea where to start]]></title><description><![CDATA[TL;DR

Start a sessiongit bisect start

Set the bad commit
 Either the current commit you're checked out has the bug
git bisect bad
or a specific commit has the bug, for example, dcf12e8
git bisect bad dcf12e8

Set the good commit (e.g. eff13d3 doesn...]]></description><link>https://erikmedina.dev/finding-a-bug-when-you-have-no-idea-where-to-start</link><guid isPermaLink="true">https://erikmedina.dev/finding-a-bug-when-you-have-no-idea-where-to-start</guid><category><![CDATA[Git]]></category><category><![CDATA[Bugs and Errors]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[terminal]]></category><category><![CDATA[programing]]></category><dc:creator><![CDATA[Erik Medina]]></dc:creator><pubDate>Tue, 08 Jun 2021 07:32:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1623047498369/mJUDl-r9_o.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-tldr">TL;DR</h2>
<ol>
<li>Start a session<pre><code>git bisect <span class="hljs-keyword">start</span>
</code></pre></li>
<li><p>Set the bad commit</p>
<p> Either the <strong>current commit</strong> you're checked out has the bug</p>
<pre><code><span class="hljs-attribute">git</span> bisect bad
</code></pre><p>or a <strong>specific commit</strong> has the bug, for example, <code>dcf12e8</code></p>
<pre><code><span class="hljs-attribute">git</span> bisect bad dcf<span class="hljs-number">12</span>e<span class="hljs-number">8</span>
</code></pre></li>
<li>Set the good commit (e.g. <code>eff13d3</code> <strong>doesn't have</strong> the bug )<pre><code><span class="hljs-attribute">git</span> bisect good eff<span class="hljs-number">13</span>d<span class="hljs-number">3</span>
</code></pre></li>
<li><p>Run and test the application yourself (you have to tell Git if the bug is there or not)</p>
<p> Either the bug is present, then run</p>
<pre><code><span class="hljs-attribute">git</span> bisect bad
</code></pre><p>or the bug is not present, then run</p>
<pre><code><span class="hljs-attribute">git</span> bisect good
</code></pre></li>
<li>Repeat step 4 until the <strong>first</strong> bad commit is found</li>
</ol>
<p><strong>Note:</strong> you can use tags instead of commit hashes as well.</p>
<h2 id="heading-when-is-it-useful">When is it useful?</h2>
<p>I usually find it quite useful when the two following conditions are met:</p>
<ul>
<li>The bug was not present in the latest release but it's present in the current release candidate</li>
<li>I have no idea what is causing the bug (therefore I don't know where to look)</li>
</ul>
<p>Imagine the following scenario. A new release (let's say 2.80) is about to be released and QA is doing regression. You're enjoying a deserved coffee after a job well done when, unexpectedly, you're tagged on Slack...you know that it's not a good signal...</p>
<p><img src="https://media.giphy.com/media/32mC2kXYWCsg0/giphy.gif" alt="D'oh!" /></p>
<p>So, you've just been informed that a blocker was found during regression and it has to be fixed. At this point, several thoughts go through your mind:</p>
<p><em>"Okay, hopefully, it's not my code that is breaking the app so I'm safe"</em> (AKA throw one of your colleagues under the bus)</p>
<p><em>"Let's look at the ticket, it will surely be something easy to fix. D'oh! It isn't!"</em></p>
<p>Okay, you have no choice but to fix it. You read the ticket and the bug is odd. You don't have a clue why it's failing and what is causing it.</p>
<p><strong>The only thing you know for sure is that 2.80 has the bug but 2.79 doesn't.</strong> Then, <code>git bisect</code> is your friend in this scenario.</p>
<h2 id="heading-how-it-works-under-the-hood">How it works under the hood</h2>
<p>Git Bisect relies on the binary search algorithm to find the <strong>first bad commit</strong> (the commit that introduced the bug). So, let's start by starting the session:</p>
<p><code>git bisect start</code></p>
<p>Then, we have to let Git know which commit has the bug for sure and which one doesn't. We know that <code>2.80</code> has the bug and that <code>2.79</code> doesn't, so:</p>
<p><code>git bisect bad 2.80</code> (or <code>git bisect bad</code> if the current commit has the bug)</p>
<p><code>git bisect good 2.79</code></p>
<p>At this point, our setup is something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623132713399/F9h5aZT0v.png" alt="Untitled Diagram.png" /></p>
<p>Then Git <strong>automatically</strong> checks out a commit in the middle and <strong>we have to run the application to check if the bug is present or not</strong>:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623132440589/DZNumo2TC.png" alt="D'oh!" /></p>
<p>Let's say that the bug is present in <strong>C3</strong> (<code>dcf12e8</code>), then we know that the second half has the bug for sure, therefore, the bug was introduced somewhere in the first half. We have to let Git know that <strong>C3</strong> has the bug:</p>
<p><code>git bisect bad dcf12e8</code></p>
<p>Now Git automatically checks out a new commit:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623133570700/lhphqFb_1.png" alt="Untitled Diagram-Page-2.png" /></p>
<p>Let's say now that the bug is not present in <strong>C1</strong> (<code>eff13d3</code>), then we have to let Git know about this:</p>
<p><code>git bisect good eff13d3</code></p>
<p>So the first half is bug-free, therefore, it is discarded. Only the <strong>C2</strong> commit is left and Git checks it out, we run the app and let's say that the bug is present. Bingo! The first bad commit has just been found (because <strong>C1</strong> is bug-free):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1623133815657/AqKim5Au0.png" alt="Untitled Diagram-Page-3.png" /></p>
<p>Finally, Git will provide you with the hash (author, date, etc.) of the first bad commit.</p>
<h2 id="heading-final-thoughts">Final thoughts</h2>
<p><code>git bisect</code> is not the Holy Grail, sometimes even if you find the commit that introduced the bug, it's simply not enough to figure out what the problem is.</p>
<p>But, even so, it's a skill that can help you to discard possible scenarios and fence the problem.</p>
<h2 id="heading-documentation">Documentation</h2>
<p>https://git-scm.com/docs/git-bisect<br />https://www.git-tower.com/learn/git/faq/git-bisect/</p>
<h2 id="heading-images-used">Images used</h2>
<p>https://unsplash.com/photos/IClZBVw5W5A</p>
]]></content:encoded></item><item><title><![CDATA[Testing With MockK]]></title><description><![CDATA[Should I use MockK in the first place?
First things first. Why add a new library for testing into the project if I already use  Mockito  and/or  Powermock and those are just fine? We tested before MockK, didn't we? What's the benefit of adding it now...]]></description><link>https://erikmedina.dev/testing-with-mockk</link><guid isPermaLink="true">https://erikmedina.dev/testing-with-mockk</guid><category><![CDATA[Testing]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Android]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[android development]]></category><dc:creator><![CDATA[Erik Medina]]></dc:creator><pubDate>Sun, 25 Apr 2021 11:19:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619349083954/BhkomLQwl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-should-i-use-mockk-in-the-first-place">Should I use MockK in the first place?</h2>
<p>First things first. Why add a new library for testing into the project if I already use  <a target="_blank" href="https://site.mockito.org/">Mockito</a>  and/or  <a target="_blank" href="https://powermock.github.io/">Powermock</a> and those are just fine? We tested before MockK, didn't we? What's the benefit of adding it now?</p>
<p> <a target="_blank" href="https://kotlinlang.org/">Kotlin</a>, the answer is Kotlin.  Google announced  Kotlin as a  <a target="_blank" href="https://android-developers.googleblog.com/2017/05/android-announces-support-for-kotlin.html">preferred language</a>  for Android at  <a target="_blank" href="https://youtu.be/EtQ8Le8-zyo?t=560">Google I/O 2017</a>. And since then, the language has become more and more popular. The latest <a target="_blank" href="https://insights.stackoverflow.com/survey/2020">Stack Overflow's Developer Survey</a> (2020) shows this trend:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616754026570/0f2JvN5-5.png" alt="image.png" /></p>
<p>So, given its first-class status in the Android ecosystem and its good reception by developers, we can say that Kotlin is here to stay. Even so, do we need MockK? If I was asked this question, I'd answer a "no". We don't need it, same as we don't need Kotlin to develop Android applications. However, I like MockK for reasons like:</p>
<h3 id="heading-interoperability">Interoperability</h3>
<p>We can test both, Java and Kotlin files, so we are not limited to only Kotlin code which means that we can test old projects written in Java with MockK.</p>
<h3 id="heading-final-classes">Final classes</h3>
<p>Is the following error familiar to you when testing Kotlin code with Mockito?</p>
<pre><code>Mockito cannot mock/spy because :
- <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span></span>
</code></pre><p>Classes in Kotlin are <code>final</code> by default to prevent inheritance (you have to define a class as <code>open</code> if you want to make it inheritable).</p>
<p>With MockK you don't need to do any workaround to fix the above error, it just works.</p>
<h3 id="heading-extension-functions">Extension functions</h3>
<p>A nice feature that we have in Kotlin to add more functionalities to classes that we do/don't own (e.g. the <code>String</code> class) are the  <a target="_blank" href="https://kotlinlang.org/docs/extensions.html">extension functions</a> and MockK gives us a handy way ( <a target="_blank" href="https://mockk.io/#extension-functions">mockkStatic()</a> ) of mocking them.</p>
<p><em>Tip: you can use <code>mockkStatic()</code> for mocking <strong>static methods</strong> in Java as well.</em></p>
<h3 id="heading-relaxed-mocks">Relaxed mocks</h3>
<p>How many times have you faced an NPE when running a test? I don't know about you but I've faced it many times myself. One of the reasons for those NPEs is that we forget to set up the behaviour of a mock, in other words, we forget to set up some <code>when(mock.doThis()).thenReturn(...)</code>.</p>
<p>We could either set up the missing responses (depending on the mock, it could mean setting up multiple <code>when</code>'s) or use  <a target="_blank" href="https://mockk.io/#relaxed-mock">relaxed mocks</a>. A relaxed mock <strong>returns some simple value for all functions</strong>. So we can just focus on setting up the behaviours that we need and forget about the rest.</p>
<p>It's worth it to mention that we can make the mock to return simple values for <strong>all functions</strong> with <code>relaxed = true</code>:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserViewModelTest</span> </span>{

    <span class="hljs-meta">@MockK(relaxed = true)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> loginService: LoginService

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span></span> {
        MockitoAnnotations.openMocks(<span class="hljs-keyword">this</span>)
     }
}
</code></pre><p>Or we can set it up for <strong>only functions that return nothing</strong> (<code>Unit</code> in Kotlin or <code>void</code> in Java):</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserViewModelTest</span> </span>{

    <span class="hljs-meta">@MockK(relaxUnitFun = true)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> loginService: LoginService

    <span class="hljs-meta">@Before</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span></span> {
        MockitoAnnotations.openMocks(<span class="hljs-keyword">this</span>)
     }
}
</code></pre><h3 id="heading-witharg-matcher">withArg matcher</h3>
<p>When testing, we may want to ensure that an argument contains an expected value. That is not a problem at all, unless this argument is only used internally within a class (either <code>private</code> property or a local argument inside a function), therefore, we can't read its value from outside the class.</p>
<p>I've seen mainly two different approaches of working this around:</p>
<ul>
<li>Make the property public so you can read it from outside (every time a developer do this, a new plague is sent to the world)</li>
<li>Annotate the property with <code>@VisibleForTesting</code> (yeah...it does the job but you can do better and you know it)</li>
</ul>
<p>The problem with those solutions is that we're modifying the <em>production</em> code for testing purposes. This smells very bad. However, there will be times (too much refactoring, need to deliver, lack of time, etc.) in which we'll have no choice but use them. I'd see them as a plan B.</p>
<p>The best approach to test the above scenario is to "capture" the private/local argument and make assertions on it. Mockito provides us with the <code>ArgumentCaptor</code> feature for this purpose.</p>
<p>Having the following code: </p>
<pre><code>    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">login</span><span class="hljs-params">(username: <span class="hljs-type">String</span>, password: <span class="hljs-type">String</span>)</span></span> {
        <span class="hljs-keyword">val</span> user = User(username, password)
        loginService.login(user)
    }
</code></pre><p>We want to ensure that we're passing the correct <code>User</code> object built from <code>username</code> and <code>password</code>. With <code>ArgumentCaptor</code>:</p>
<pre><code>    @Test
    fun `Argument Captor`() {
        val captor <span class="hljs-operator">=</span> argumentCaptor<span class="hljs-operator">&lt;</span>User<span class="hljs-operator">&gt;</span>()<span class="hljs-comment">// first step</span>
        val username <span class="hljs-operator">=</span> <span class="hljs-string">"myusername@company.com"</span>
        val password <span class="hljs-operator">=</span> <span class="hljs-string">"12345"</span>
        val userExpected <span class="hljs-operator">=</span> User(username, password)

        sut.login(username, password)

        verify(loginService).login(captor.capture())<span class="hljs-comment">// second step</span>
        assertEquals(userExpected, captor.firstValue)<span class="hljs-comment">// third step</span>
    }
</code></pre><p>As we can see, we have to follow three steps (define, capture and assertion). </p>
<p>These three steps can be reduced with <code>withArg</code>:</p>
<pre><code>    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> `WithArg`<span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">val</span> username = <span class="hljs-string">"myusername@company.com"</span>
        <span class="hljs-keyword">val</span> password = <span class="hljs-string">"12345"</span>
        <span class="hljs-keyword">val</span> userExpected = User(username, password)

        sut.login(username, password)

        verify {
            persistUsersUseCase.login(
                withArg { assertEquals(userExpected, it) }<span class="hljs-comment">// capture and assertion</span>
            )
        }
    }
</code></pre><p>Things that I like with this approach:</p>
<ul>
<li>I don't have to define the captor</li>
<li>I don't have to explicitly capture the value</li>
<li>I can do everything in just one verification</li>
</ul>
<h2 id="heading-to-conclude">To conclude</h2>
<p>MockK has much more to offer and helps to achieve more writing less. In my first contact with it, I wasn't very happy about having to learn a new tool and I didn't see many advantages of using it (just some specific scenarios) but nowadays I'm happy I gave it a go and it's become an essential in my toolbox.</p>
<h3 id="heading-bibliography">Bibliography</h3>
<p>https://mockk.io/ (official page)</p>
<p>https://blog.kotlin-academy.com/mocking-is-not-rocket-science-mockk-features-e5d55d735a98 (article written by the developer/author of MockK)</p>
<p>https://notwoods.github.io/mockk-guidebook/ (guidebook)</p>
]]></content:encoded></item><item><title><![CDATA[Is Unit Testing Really That Important?]]></title><description><![CDATA[Short answer: Yes.
Long answer: Yes, Unit Testing is that important.

If you just searched the web for unit testing, congratulations! You're on the right track. The sooner you start including tests in your code the better. 
I wish I knew this when I ...]]></description><link>https://erikmedina.dev/is-unit-testing-really-that-important</link><guid isPermaLink="true">https://erikmedina.dev/is-unit-testing-really-that-important</guid><category><![CDATA[unit testing]]></category><category><![CDATA[software]]></category><category><![CDATA[Career]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Erik Medina]]></dc:creator><pubDate>Tue, 23 Mar 2021 19:41:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616527954758/FHp6PQbMD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Short answer: Yes.</p>
<p>Long answer: Yes, Unit Testing is that important.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1616527213087/8uoD2Crrm.jpeg" alt="52uxzb.jpg" /></p>
<p>If you just searched the web for unit testing, congratulations! You're on the right track. The sooner you start including tests in your code the better. </p>
<p>I wish I knew this when I started my career as an Android developer. I remember being taught about using design patterns such as  <a target="_blank" href="https://www.journaldev.com/14886/android-mvp">MVP</a> for decoupling the business logic from the view business and thus, among other things,  have testable code. However, we didn't implement tests therefore I never really internalise the benefits of using design patterns nor unit testing. It seemed to me that it only made the project more difficult to understand and follow, code more verbose and I ended up coding in that way because "it was how it was supposed to be done".</p>
<p>It took me years to understand the importance of design patterns and unit testing (that's why it's important to start with unit testing soon) but once you do it, you'll never look back and this is great news.</p>
<p>There are several benefits, technical and non-technical, about unit testing that I've found out over the years.</p>
<h2 id="heading-technical-benefits">Technical benefits</h2>
<h3 id="heading-improve-our-code">Improve our code</h3>
<p>We always write clean code, right? RIGHT!? Well, no...not always at least. Unit testing helps us to spot complex logic (e.g. a method that does many things or a bunch of required setup in the test file is a strong indicator that the class under test could be doing many things as well) because complex logic is not easy to test, therefore we may want to refactor it and make it easier to test.</p>
<p>More than once I've had the following thought <em>"Wait...I think I've tested this same behaviour before..."</em>. And effectively I find that I already have that same (or similar) logic implemented in the codebase so it's a strong candidate for being extracted as a helper or util and being reused, thus avoid code duplication.</p>
<h3 id="heading-make-our-code-more-reliable">Make our code more reliable</h3>
<p>For a Java developer, a crash of the application due to an NPE is as frequent as a lockdown nowadays. The reason is that when you're coding, it's not rare that you take for granted that most of the variables have a value assigned. This is not always the case and testing highlights it before our eyes. You are not going to fix something if you don't even know it's broken. I've named NPE but it applies to more things such as missing to consider conditional branches (if-else).</p>
<h3 id="heading-spot-edge-cases">Spot edge cases</h3>
<p>When we code, we think about all the possibilities and/or scenarios that our app may face and we cover them. Or at least we think so. It's very common that when we're testing a piece of code, we find ourselves having the following conversation:</p>
<p><em>"Okay, so this method receives a list as an argument and it can't be null because I've annotated it as <code>@NonNull</code> therefore I don't have to test the scenario in which the list is null, yeah!!! Hold on, what if the list is empty?"</em></p>
<p>At this point, new questions arise:</p>
<ul>
<li>Should I treat an empty list as an error?</li>
<li>Should I add a default value/object to the list when it is empty?</li>
<li>Should I handle the empty list in this method or should the caller to the method handle it and ensure that the list is not empty?</li>
</ul>
<p>Something as simple as an empty list is a source of questions and unit testing begins to show its power.</p>
<h3 id="heading-encourage-refactoring">Encourage refactoring</h3>
<p>Our tests work as a safety net for our production code so, if we have a good test suite, we'll be more willing to refactor if we know unconsciously that we won't break anything without being warned.</p>
<h2 id="heading-non-technical-benefits">Non-technical benefits</h2>
<h3 id="heading-stand-out">Stand out</h3>
<p>If you're a less experienced developer in job hunting, knowing about unit testing (even if you're not that great at it yet) can make you stand out among other candidates.</p>
<p>And if you're a more experienced developer and you don't know about testing, you will stand out as well. Not in the way that you want to though.</p>
<h3 id="heading-detect-red-flags">Detect red flags</h3>
<p>If during an interview, you're not asked about unit testing or when you ask about it (you should always ask questions in an interview by the way), the interviewer gives you a vague answer (no mention about code coverage, tools for code quality such as  <a target="_blank" href="https://www.sonarqube.org/">SonarQube</a>, frameworks for testing such as  <a target="_blank" href="https://site.mockito.org/">Mockito</a>  and  <a target="_blank" href="http://robolectric.org/">Robolectric</a>) for Android, then you know that you have to be in alert to spot more red flags "Do they have code review? What about their CI/CD?" If you spot a lot of red flags, you might want to consider if that is a place where you want to work.</p>
<h2 id="heading-downsides">Downsides</h2>
<h3 id="heading-time-consuming">Time-consuming</h3>
<p>Frequently, you spend more time testing the production code you just wrote than writing the code itself. Especially when you're not used to testing or, even worse, when you have to test legacy code that was never tested, therefore likely not very testable.</p>
<h3 id="heading-clashes-with-teammates">Clashes with teammates</h3>
<p>If you work in a company in which the culture of testing is little or your teammates barely test their code because they think that testing is not important or a waste of time, most likely there will be frictions. You may need to make the extra effort and educate them.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In my experience, you should add unit testing to your skill set because the benefits outweigh the downsides and there is no turning back. It makes you a better developer because it obliges you to architecture your app, to think about why you're doing things in some way and not in another, to understand why concepts such as single responsibility or decoupling are important and the like. </p>
]]></content:encoded></item></channel></rss>