{"id":395,"date":"2025-03-04T17:55:29","date_gmt":"2025-03-04T17:55:29","guid":{"rendered":"https:\/\/imcodinggenius.com\/?p=395"},"modified":"2025-03-04T17:55:29","modified_gmt":"2025-03-04T17:55:29","slug":"mockk-objects-top-level-and-extension-functions-3-5","status":"publish","type":"post","link":"https:\/\/imcodinggenius.com\/?p=395","title":{"rendered":"MockK: Objects, Top-Level, and Extension Functions [3\/5]"},"content":{"rendered":"<p>This tutorial is a great example of why MockK is an excellent choice for Kotlin and how easy we can work with Kotlin features, such as the previously mentioned objects.<\/p>\n<p>Of course, you can find the rest of the series on my blog, too:<\/p>\n<p><a href=\"https:\/\/codersee.com\/getting-started-with-mockk-kotlin\/\">Getting Started with MockK in Kotlin [1\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/verification-mockk\/\">Verification in MockK [2\/5]<\/a><\/p>\n<p>MockK: Objects, Top-Level, and Extension Functions [3\/5]<\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-spy-relaxed-mock-partial-mocking\/\">MockK: Spies, Relaxed Mocks, and Partial Mocking [4\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-coroutines\/\">MockK with Coroutines [5\/5]<\/a><\/p>\n<h2 class=\"wp-block-heading\">Kotlin Objects and MockK<\/h2>\n<p>Let\u2019s start everything by explaining <strong>how to mock Kotlin objects in MockK<\/strong>.<\/p>\n<p>And as you know, objects are pretty specific, so we are going to see two, different examples and approaches.<\/p>\n<h3 class=\"wp-block-heading\">mockkObject<\/h3>\n<p>Let\u2019s introduce a simple example with an object:<\/p>\n<p>class One {<br \/>\n    fun funToTest(): UUID = SomeObject.generateId()<br \/>\n}<\/p>\n<p>object SomeObject {<br \/>\n    fun generateId(): UUID = UUID.randomUUID()<br \/>\n}<\/p>\n<p>It is not rocket science, right? We are going to simply test the function that should return the UUID generated by SomeObject function.<\/p>\n<p>So, if we would like to mock that UUID to gain more control over the behavior, then we can use the mockkObject:<\/p>\n<p>class OneTest {<\/p>\n<p>    private val one = One()<\/p>\n<p>    @Test<br \/>\n    fun `should return mocked ID`() {<br \/>\n        val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>        mockkObject(SomeObject)<br \/>\n        every { SomeObject.generateId() } returns id<\/p>\n<p>        val result = one.funToTest()<\/p>\n<p>        assertEquals(id, result)<br \/>\n    }<br \/>\n}<\/p>\n<p>The above test succeeds, and we can see that we define stubbing just like with every mock.<\/p>\n<p>Moreover, if we add mockkObject inside the function, it will not affect the scope of other tests:<\/p>\n<p>class OneTest {<\/p>\n<p>    private val one = One()<\/p>\n<p>    @Test<br \/>\n    fun `should return mocked ID`() {<br \/>\n        val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>        mockkObject(SomeObject)<br \/>\n        every { SomeObject.generateId() } returns id<\/p>\n<p>        val result = one.funToTest()<\/p>\n<p>        assertEquals(id, result)<br \/>\n    }<\/p>\n<p>    @Test<br \/>\n    fun `should fail returning mocked ID`() {<br \/>\n        val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>        val result = one.funToTest()<\/p>\n<p>        assertEquals(id, result)<br \/>\n    }<br \/>\n}<\/p>\n<p>This time, the second test fails because SomeObject returns a <strong>random value.<\/strong><\/p>\n<p>Additionally, if we use the mockkObject , but we don\u2019t provide stubbing, <strong>MockK will not throw any exception:<\/strong><\/p>\n<p>@Test<br \/>\nfun `should fail returning mocked ID`() {<br \/>\n    val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    mockkObject(SomeObject)<br \/>\n    val result = one.funToTest()<\/p>\n<p>    assertEquals(id, result)<br \/>\n}<\/p>\n<p>The above test runs just like mockkObject(SomeObject) does not exist. As a result, we get a random UUID.<\/p>\n<p>So, we must be cautious about that.<\/p>\n<h3 class=\"wp-block-heading\">unmockkObject<\/h3>\n<p>Although I highly doubt we should ever use that, MockK allows us to \u201cunmock\u201d the object with unmockkObject function.<\/p>\n<p>How does it work?<\/p>\n<p>Let\u2019s analyze the below snippet:<\/p>\n<p>@Test<br \/>\nfun `should illustrate unmockkObject`() {<br \/>\n    val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    mockkObject(SomeObject)<br \/>\n    every { SomeObject.generateId() } returns id<\/p>\n<p>    assertEquals(id, one.funToTest())<\/p>\n<p>    unmockkObject(SomeObject)<br \/>\n    assertEquals(id, one.funToTest())<br \/>\n}<\/p>\n<p>In this example, the first assertion succeeds. However, the second assertEquals fails due to unmockkObject that reverts our mock.<\/p>\n<p>So, again, during the second call, a random UUID is generated.<\/p>\n<h3 class=\"wp-block-heading\">Create Mock Object Instance<\/h3>\n<p>I know, this title sounds simply weird.<\/p>\n<p>Nevertheless, let\u2019s take a look at another class- Two :<\/p>\n<p>class Two(<br \/>\n    private val someObject: SomeObject,<br \/>\n) {<br \/>\n    fun funToTest(): UUID = someObject.generateId()<br \/>\n}<\/p>\n<p>This time, we inject our SomeObject through the constructor.<\/p>\n<p>And for consistency, in MockK, we can mock that just like a simple class:<\/p>\n<p>class TwoTest {<\/p>\n<p>    private val someObject = mockk&lt;SomeObject&gt;()<br \/>\n    private val two = Two(someObject)<\/p>\n<p>    @Test<br \/>\n    fun `should return mocked ID`() {<br \/>\n        val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>        every { someObject.generateId() } returns id<\/p>\n<p>        val result = two.funToTest()<\/p>\n<p>        assertEquals(id, result)<br \/>\n    }<br \/>\n}<\/p>\n<p>But, <strong>we must remember about two, important things in this case.<\/strong><\/p>\n<p>Firstly, we <strong>must provide a stubbing<\/strong>:<\/p>\n<p>@Test<br \/>\nfun `should fail due to missing stubbing`() {<br \/>\n    val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    val result = two.funToTest()<\/p>\n<p>    assertEquals(id, result)<br \/>\n}<\/p>\n<p>So, just like with classes, the above test fails due to missing stubbing!<\/p>\n<p>Secondly, when defining stubbing, we <strong>must use the instance<\/strong>:<\/p>\n<p>@Test<br \/>\nfun `should fail due to incorrect stubbing`() {<br \/>\n    val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    every { SomeObject.generateId() } returns id<\/p>\n<p>    val result = two.funToTest()<\/p>\n<p>    assertEquals(id, result)<br \/>\n}<\/p>\n<p>As we can see, we cannot refer to the SomeObject anymore.<\/p>\n<p>So, as always, the choice is up to you. <\/p>\n<h2 class=\"wp-block-heading\">MockK and Top-Level Functions<\/h2>\n<p>With all of that said about objects, let\u2019s take a look at how we can deal with another Kotlin feature, <strong>top-level functions<\/strong>, in MockK.<\/p>\n<p>As the first step, let\u2019s take a look at the code to test:<\/p>\n<p>class Three {<br \/>\n    fun funToTest(): UUID = generateId()<br \/>\n}<\/p>\n<p>fun generateId(): UUID = UUID.randomUUID()<\/p>\n<p>This time, instead of the object and its function, we\u2019re dealing with top-level generateId .<\/p>\n<p>And from the MockK perspective, everything looks pretty much the same as with objects:<\/p>\n<p>class ThreeTest {<\/p>\n<p>    private val three = Three()<\/p>\n<p>    @Test<br \/>\n    fun `should return mocked ID`() {<br \/>\n        val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>        mockkStatic(::generateId)<br \/>\n        every { generateId() } returns id<\/p>\n<p>        val result = three.funToTest()<\/p>\n<p>        assertEquals(id, result)<br \/>\n    }<br \/>\n}<\/p>\n<p>As we can see, we use the mockkStatic and we simply provide our stubbing.<\/p>\n<p>And just like in the first approach in objects, nothing happens if we define the mockkStatic , but we don\u2019t set the stubbing. The random UUID is generated:<\/p>\n<p>@Test<br \/>\nfun `should fail due to missing stubbing`() {<br \/>\n    val id = UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    mockkStatic(::generateId)<\/p>\n<p>    val result = three.funToTest()<\/p>\n<p>    assertEquals(id, result)<br \/>\n}<\/p>\n<p>Lastly, I just wanted to mention that we have a similar function- clearStaticMockk\u2013 on the table, too<\/p>\n<h2 class=\"wp-block-heading\">Extension Functions Support<\/h2>\n<p>As the last thing in this article, let\u2019s take a look at the example leveraging the extension function:<\/p>\n<p>class Four {<br \/>\n    fun funToTest(): String = &#171;abc&#187;.withCustomCase()<br \/>\n}<\/p>\n<p>fun String.withCustomCase(): String = this.uppercase()<\/p>\n<p>It does not make too much sense, but we can clearly see that our extension function should return an uppercase String value.<\/p>\n<p>And to mock this case in MockK, we can use mockkStatic once again:<\/p>\n<p>class FourTest {<\/p>\n<p>    private val four = Four()<\/p>\n<p>    @Test<br \/>\n    fun `should return codersee`() {<br \/>\n        mockkStatic(String::withCustomCase)<br \/>\n        every { &#171;abc&#187;.withCustomCase() } returns &#171;codersee&#187;<br \/>\n        every { &#171;xyz&#187;.withCustomCase() } returns &#171;not-codersee&#187;<\/p>\n<p>        val result = four.funToTest()<\/p>\n<p>        assertEquals(&#171;codersee&#187;, result)<br \/>\n    }<br \/>\n}<\/p>\n<p>The really interesting part in the above snippet is that the String value <strong>must match!<\/strong><\/p>\n<p>Additionally, MockK allows us to mock extension functions defined in a class.<\/p>\n<p>Nevertheless, in my opinion this case is so rare, that I will skip it. And if you really need to check it, then take a look at the documentation <a href=\"https:\/\/mockk.io\/#extension-functions\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n<p>That\u2019s all for the third article, in which we learned how to deal with Kotlin objects, top-level and extension functions in MockK.<\/p>\n<p>Great job, and without any further ado, let\u2019s head to the next lesson:<\/p>\n<p><a href=\"https:\/\/codersee.com\/getting-started-with-mockk-kotlin\/\">Getting Started with MockK in Kotlin [1\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/verification-mockk\/\">Verification in MockK [2\/5]<\/a><\/p>\n<p>MockK: Objects, Top-Level, and Extension Functions [3\/5]<\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-spy-relaxed-mock-partial-mocking\/\">MockK: Spies, Relaxed Mocks, and Partial Mocking [4\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-coroutines\/\">MockK with Coroutines [5\/5]<\/a><\/p>\n<p>The post <a href=\"https:\/\/codersee.com\/mockk-objects-top-level-extension-functions\/\">MockK: Objects, Top-Level, and Extension Functions [3\/5]<\/a> appeared first on <a href=\"https:\/\/codersee.com\/\">Codersee &#8212; Kotlin on the backend<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>This tutorial is a great example of why MockK is an excellent choice for Kotlin and how easy we can work with Kotlin features, such as the previously mentioned objects. Of course, you can find the rest of the series on my blog, too: Getting Started with MockK in Kotlin &#8230; <\/p>\n<div><a class=\"more-link bs-book_btn\" href=\"https:\/\/imcodinggenius.com\/?p=395\">Read More<\/a><\/div>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-395","post","type-post","status-publish","format-standard","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts\/395"}],"collection":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=395"}],"version-history":[{"count":0,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts\/395\/revisions"}],"wp:attachment":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}