<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kotlin Archives - Codersee blog- Kotlin on the backend</title>
	<atom:link href="https://blog.codersee.com/category/kotlin/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.codersee.com/category/kotlin/</link>
	<description>Kotlin &#38; Backend Tutorials - Learn Through Practice.</description>
	<lastBuildDate>Thu, 17 Apr 2025 09:45:17 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.codersee.com/wp-content/uploads/2025/04/cropped-codersee_logo_circle_2-32x32.png</url>
	<title>Kotlin Archives - Codersee blog- Kotlin on the backend</title>
	<link>https://blog.codersee.com/category/kotlin/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>A Quick Guide to htmx in Kotlin</title>
		<link>https://blog.codersee.com/quick-quide-to-htmx-kotlin/</link>
					<comments>https://blog.codersee.com/quick-quide-to-htmx-kotlin/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Sat, 29 Mar 2025 17:25:53 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Ktor]]></category>
		<category><![CDATA[htmx]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=18012838</guid>

					<description><![CDATA[<p>In this tutorial, we will learn the most important htmx concepts and create a basic application with Kotlin HTML DSL and Tailwind CSS.</p>
<p>The post <a href="https://blog.codersee.com/quick-quide-to-htmx-kotlin/">A Quick Guide to htmx in Kotlin</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>To be more specific, we will see a step-by-step process of writing <strong>HTML </strong>with typesafe <strong>Kotlin DSL</strong>, integrating <strong>htmx</strong>, and handling requests with <strong>Ktor</strong>. </p>



<p>Eventually, we will get the below user table:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="521" src="http://blog.codersee.com/wp-content/uploads/2025/03/htmx_kotlin_app_screen-1024x521.webp" alt="Image presents a screenshot of result application created in Kotlin and htmx." class="wp-image-18012839" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/htmx_kotlin_app_screen-1024x521.webp 1024w, https://blog.codersee.com/wp-content/uploads/2025/03/htmx_kotlin_app_screen-300x153.webp 300w, https://blog.codersee.com/wp-content/uploads/2025/03/htmx_kotlin_app_screen-768x391.webp 768w, https://blog.codersee.com/wp-content/uploads/2025/03/htmx_kotlin_app_screen.webp 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p></p>



<p>But before we start, just a short disclaimer: although the main focus for this tutorial is the htmx / Kotlin / Ktor combination, I decided to bring <strong>Tailwind CSS</strong> to the project with the help of <a href="https://www.material-tailwind.com/" target="_blank" rel="noreferrer noopener nofollow">Material Tailwind components</a>. This way, I wanted to showcase the code that is closer to real-life scenarios. Not a next, plain HTML example. </p>



<p>So, although I tried my best, please keep in mind that the HTML part may need some more love when adapting 🫡</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: if you enjoy this content and would like to learn Ktor step-by-step, then check out my <a href="https://codersee.com/courses/ktor-server-pro/">Ktor Server Pro course</a>.</p>
</blockquote>



<h2 class="wp-block-heading" id="h-video-tutorial">Video Tutorial</h2>



<p>If you prefer <strong>video content</strong>, then check out my video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/quick-quide-to-htmx-kotlin/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FtstB08EDClw%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-what-is-htmx">What is htmx? </h2>



<p>If you are here, then there is a high chance you&#8217;ve been looking for a Kotlin &amp; htmx combination, so you already know what it is. </p>



<p>Nevertheless, so we are all on on the same page: </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>It is a library that allows you to access modern browser features directly from HTML, rather than using javascript.</p>
</blockquote>



<p>And we could add plenty of other things here, like the fact that it is small, dependency-free, and allows us to use AJAX, CSS Transitions, WebSockets, and so on. </p>



<p>But, IMO, the most important thing from the practical standpoint is that we can use attributes in HTML, and the library will do the &#8220;magic&#8221; for us:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;td>
  &lt;button hx-delete="/users/7a9079f0-c5a2-45d0-b4ae-e304b6908787" hx-swap="outerHTML" hx-target="closest tr">
... the rest
   </pre>



<p>The above following snippet means that when we click the button:</p>



<ul class="wp-block-list">
<li>the <code>DELETE /users/7a9079f0-c5a2-45d0-b4ae-e304b6908787</code> request is made</li>



<li>the closest tr element is replaced with the HTML response we receive</li>
</ul>



<p>And I believe this is all we need to know for now. </p>



<p>Again, a short note from my end: the <a href="https://htmx.org/docs/" target="_blank" rel="noreferrer noopener">htmx documentation</a> is a great resource, and I will refer a lot to it throughout this course to not reinvent the wheel. But at the same time, I want to deliver you a fully-contained article so that you don&#8217;t need to jump between pages 😉</p>



<h2 class="wp-block-heading" id="h-generate-ktor-project">Generate Ktor Project</h2>



<p>As the first step, let&#8217;s quickly generate a new Ktor project using <a href="https://start.ktor.io/">https://start.ktor.io/</a>:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="590" src="http://blog.codersee.com/wp-content/uploads/2025/03/ktor_htmx_kotlin_html_dsl-1024x590.png" alt="" class="wp-image-18012840" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/ktor_htmx_kotlin_html_dsl-1024x590.png 1024w, https://blog.codersee.com/wp-content/uploads/2025/03/ktor_htmx_kotlin_html_dsl-300x173.png 300w, https://blog.codersee.com/wp-content/uploads/2025/03/ktor_htmx_kotlin_html_dsl-768x443.png 768w, https://blog.codersee.com/wp-content/uploads/2025/03/ktor_htmx_kotlin_html_dsl.png 1277w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>As we can see, the only plugin we need to select is the <strong>Kotlin HTML DSL </strong>(this way, the Routing plugin is added, too).</p>



<p>Regarding the config, we are going to use <strong>Ktor 3.1.1</strong> with <strong>Netty</strong>, <strong>YAML </strong>config, and <strong>without a version catalog</strong>. But, of course, feel free to adjust it here according to your needs.</p>



<p>With that done, let&#8217;s download the project and import it to our IDE. </p>



<h2 class="wp-block-heading" id="h-create-user-repository">Create User Repository</h2>



<p>Following, let&#8217;s add the <code>repository</code> package and introduce a simple, in-memory user repository:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class User(
    val id: String = UUID.randomUUID().toString(),
    val firstName: String,
    val lastName: String,
    val enabled: Boolean,
    val createdAt: LocalDateTime = LocalDateTime.now(),
)
class UserRepository {
    private val users = mutableListOf(
        User(firstName = "Jane", lastName = "Doe", enabled = true),
        User(firstName = "John", lastName = "Smith", enabled = true),
        User(firstName = "Alice", lastName = "Johnson", enabled = false),
        User(firstName = "Bob", lastName = "Williams", enabled = true),
    )
    fun create(firstName: String, lastName: String, enabled: Boolean): User =
        User(firstName = firstName, lastName = lastName, enabled = enabled)
            .also(users::add)
    fun findAll(): List&lt;User> = users
    fun delete(id: String): Boolean = users.removeIf { it.id == id }
}</pre>



<p>As we can see, nothing spectacular. Just 3 functions responsible for creating, searching, and deleting users. </p>



<h2 class="wp-block-heading" id="h-return-html-response-in-ktor">Return HTML Response in Ktor</h2>



<p>Following, let&#8217;s add the <code>routing</code> package and <code>Routing.kt</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun Application.configureRouting(userRepository: UserRepository) {
    routing {
        get("/") {
            call.respondHtml {
                renderIndex(userRepository)
            }
        }
    }
}</pre>



<p>And update the main <code>Application.kt</code> to incorporate those changes: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun Application.module() {
    val userRepository = UserRepository()
    configureRouting(userRepository)
}</pre>



<p>In a moment, we will add the <code>renderIndex</code> function, but for now, let&#8217;s focus on the above. </p>



<p>Long story short, the above code instructs the Ktor server to respond with the HTML response whenever it reaches the root path. By default, the <code>localhost:8080</code>. </p>



<h2 class="wp-block-heading" id="h-generate-html-page-with-kotlin-dsl">Generate HTML page with Kotlin DSL</h2>



<p>With that done, we have everything we need to start returning HTML responses. So in this section, we will prepare the baseline for htmx. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: if you feel that continuous server restarting is painful, please check out <a href="https://blog.codersee.com/ktor-auto-reload/">how to enable auto-reload in Ktor?</a>  </p>
</blockquote>



<h3 class="wp-block-heading" id="h-render-homepage">Render Homepage</h3>



<p>As the first step, let&#8217;s add the <code>html</code> package and the <code>renderIndex</code> function in <code>Index.kt</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import com.codersee.repository.UserRepository
import kotlinx.html.*
fun HTML.renderIndex(userRepository: UserRepository) {
    body {
        div {
            insertHeader()
        }
    }
}
private fun FlowContent.insertHeader() {
    h5 {
        +"Users list"
    }
}</pre>



<p>At this point, such a structure is overengineering. Nevertheless, our codebase is about to grow quickly in this tutorial, so we rely on Kotlin extension functions from the very beginning. </p>



<p>And as we can see, we use the HTML that represents the root element of an HTML document. Inside it, we can define the structure in a type-safe manner, thanks to the <a href="https://blog.codersee.com/kotlin-type-safe-builders-make-your-custom-dsl/">Kotlin DSL</a> feature. For the inner tags, we can use the <code>FlowContent</code> that is the marker interface for plenty of classes representing HTML tags, like div, headers, or the body.</p>



<p>And before we rerun the application, we must add the necessary import in <code>Routing.kt</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import com.codersee.repository.html.renderIndex</pre>



<p>With that done, let&#8217;s rerun the application and verify that everything is working. </p>



<h3 class="wp-block-heading" id="h-insert-html-form">Insert HTML Form</h3>



<p>Following, let&#8217;s use the HTML DSL to define the user form. </p>



<p>As the first step, let&#8217;s add the <code>Form.kt</code> to inside the <code>html</code> package:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.html.*
fun FlowContent.insertUserForm() {
    div {
        form {
            div {
                div {
                    label {
                        htmlFor = "first-name"
                        +"First Name"
                    }
                    input {
                        type = InputType.text
                        name = "first-name"
                        id = "first-name"
                        placeholder = "First Name"
                    }
                }
                div {
                    label {
                        htmlFor = "last-name"
                        +"Last Name"
                    }
                    input {
                        type = InputType.text
                        name = "last-name"
                        id = "last-name"
                        placeholder = "Last Name"
                    }
                }
                div {
                    label {
                        +"Account enabled"
                    }
                    div {
                        div {
                            input {
                                type = InputType.radio
                                name = "enabled-radio"
                                id = "radio-button-1"
                                value = "true"
                            }
                            label {
                                htmlFor = "radio-button-1"
                                +"Yes"
                            }
                        }
                        div {
                            input {
                                type = InputType.radio
                                name = "enabled-radio"
                                id = "radio-button-2"
                                value = "false"
                                checked = true
                            }
                            label {
                                htmlFor = "radio-button-2"
                                +"No"
                            }
                        }
                    }
                }
                div {
                    button {
                        +"Add user"
                    }
                }
            }
        }
    }
}</pre>



<p>As we can see, the <strong>Kotlin DSL allows us to define everything in a neat, structured manner</strong>. And although I had a chance to use it in various places, with HTML, it feels so&#8230;natural. We write the code pretty similar to HTML.</p>



<p>Of course, before heading to the next part, let&#8217;s make use of our function: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    body {
        div {
            insertHeader()
            insertUserForm()
        }
    }
}</pre>



<p>We can clearly see that the extraction was a good idea 😉 </p>



<h3 class="wp-block-heading" id="h-create-user-table">Create User Table</h3>



<p>As the next step, let&#8217;s add the <code>UserTable.kt</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import com.codersee.repository.User
import kotlinx.html.*
import java.time.format.DateTimeFormatter
fun FlowContent.insertUserTable(users: List&lt;User>) {
    div {
        table {
            thead {
                tr {
                    th {
                        +"User"
                    }
                    th {
                        +"Status"
                    }
                    th {
                        +"Created At"
                    }
                    th {}
                }
            }
            tbody {
                id = "users-table"
                users.forEach { user ->
                    tr {
                        insertUserRowCells(user)
                    }
                }
            }
        }
    }
}
fun TR.insertUserRowCells(user: User) {
    td {
        div {
            p {
                +"${user.firstName} ${user.lastName}"
            }
        }
    }
    td {
        div {
            div {
                val enabledLabel = if (user.enabled) "Enabled" else "Disabled"
                val labelColor = if (user.enabled) "green" else "red"
                span { +enabledLabel }
            }
        }
    }
    td {
        p {
            +user.createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
        }
    }
    td {
        button {
            + "Delete"
        }
    }
}</pre>



<p>As we can see this time, the Kotlin HTML DSL allows us to easily generate <strong>dynamic HTML tags</strong>. We use the passed user list to create a row for every user we &#8220;persisted&#8221;. We even make the decision about the label and future color based on the list. </p>



<p>Again, let&#8217;s get back to <code>Routing.kt</code> and invoke our function:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    body {
        div {
            insertHeader()
            insertUserForm()
            insertUserTable(userRepository.findAll())
        }
    }
}
</pre>



<p>And although I am pretty sure it won&#8217;t become the eighth wonder of the World, our application starts looking similar to what we want to achieve:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="382" height="428" src="http://blog.codersee.com/wp-content/uploads/2025/03/ktor_kotlin_html_dsl_plain_application_screen.png" alt="Image is a screenshot of a plain HTML application generated with Kotlin HTML DSL in Ktor" class="wp-image-18512857" style="object-fit:cover" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/ktor_kotlin_html_dsl_plain_application_screen.png 382w, https://blog.codersee.com/wp-content/uploads/2025/03/ktor_kotlin_html_dsl_plain_application_screen-268x300.png 268w" sizes="(max-width: 382px) 100vw, 382px" /></figure>



<h2 class="wp-block-heading" id="h-htmx-and-kotlin">htmx and Kotlin</h2>



<p>With all of that done, we have everything prepared to start actually working with <strong>htmx and Kotlin</strong>.</p>



<p>Again, you will see a lot of references taken from the <a href="https://htmx.org/docs/">docs</a> (which I encourage you to visit after this tutorial).</p>



<h3 class="wp-block-heading" id="h-import"> Import</h3>



<p>As the first step, let&#8217;s import <strong>htmx</strong>. </p>



<p>Again, it is nothing else than the JavaScript library, so the only thing we need is to add it inside the script block of our HTML. </p>



<p>And the easiest way is to simply fetch it from their CDN and put it inside the Kotlin <code>script</code> DSL block:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    head {
        script {
            src = "https://unpkg.com/htmx.org@2.0.4"
        }
    }
    body {
        div {
            insertHeader()
            insertUserForm()
            insertUserTable(userRepository.findAll())
        }
    }
}</pre>



<h3 class="wp-block-heading" id="h-ajax-requests-create-user">AJAX Requests &#8211; Create User</h3>



<p>As we saw in the very beginning, htmx allows us to define requests with attributes. </p>



<p>To be more specific, we can use the following attributes: </p>



<ul class="wp-block-list">
<li>hx-get</li>



<li>hx-post</li>



<li>hx-put</li>



<li>hx-patch</li>



<li>hx-delete</li>
</ul>



<p>And, long story short, when the element is triggered, an AJAX request is made to the specified URL.</p>



<p>So, let&#8217;s update our form then: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun FlowContent.insertUserForm() {
    div {
        form {
            attributes["hx-post"] = "/users"
... the rest</pre>



<p>This way, our html now contains:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;form hx-post="/users"></pre>



<p>And when we hit the <code>Add user</code> button, we can see that the request is triggered (but, it results in <code>404</code> response given we have no handler). </p>



<p>So, let&#8217;s add the endpoint responsible for user creation: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun Application.configureRouting(userRepository: UserRepository) {
    routing {
        get("/") {
            call.respondHtml {
                renderIndex(userRepository)
            }
        }
        route("/users") {
            post {
                val formParams = call.receiveParameters()
                val firstName = formParams["first-name"]!!
                val lastName = formParams["last-name"]!!
                val enabled = formParams["enabled-radio"]!!.toBoolean()
                val createdItem = userRepository.create(firstName, lastName, enabled)
                val todoItemHtml = createHTML().tr { insertUserRowCells(createdItem) }
                call.respondText(
                    todoItemHtml,
                    contentType = ContentType.Text.Html,
                )
            }
        }
    }
}</pre>



<p>At this point, it should not be a surprise, but we can see that in Ktor, we can do that quite easily. </p>



<p>Our code snippet will read the form parameters sent from the browser, &#8220;create&#8221; a new user, and return a <code>200 OK</code> response with:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="html" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;tr>
  &lt;td>
    &lt;div>
      &lt;p>Admiral Jahas&lt;/p>
    &lt;/div>
  &lt;/td>
  &lt;td>
    &lt;div>
      &lt;div>&lt;span>Disabled&lt;/span>&lt;/div>
    &lt;/div>
  &lt;/td>
  &lt;td>
    &lt;p>2025-03-29 08:16:40&lt;/p>
  &lt;/td>
  &lt;td>&lt;button>Delete&lt;/button>&lt;/td>
&lt;/tr>
</pre>



<p>The <strong>important </strong>thing to mention here is that <code>respondHtml</code> requires us to respond with whole body! So, to bypass that, we use the <code>respondText</code> function and set the content type as HTML. </p>



<p>However, when we open up the browser, we can see this:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="388" height="362" src="http://blog.codersee.com/wp-content/uploads/2025/03/image-3.png" alt="Image is a screenshot from htmx POST invocation with invalid target." class="wp-image-18512868" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/image-3.png 388w, https://blog.codersee.com/wp-content/uploads/2025/03/image-3-300x280.png 300w" sizes="auto, (max-width: 388px) 100vw, 388px" /></figure>



<p>And I am pretty sure that is not what we wanted 😀 </p>



<h3 class="wp-block-heading" id="h-htmx-target">htmx Target</h3>



<p><strong>Lesson one:</strong> if we want to instruct htmx to load the response into a different element than the one that made the request, we must use the <code>hx-target</code> attribute that takes the CSS selector, or:</p>



<ul class="wp-block-list">
<li><code>this</code> keyword- to refer to the element with <code>hx-target</code> attribute</li>



<li><code>closest</code>, <code>next</code>, <code>previous</code> <code>&lt;CSS selector&gt;</code> (like <code>closest div</code>)- to target the closest ancestor element or itself</li>



<li><code>find &lt;CSS selector</code> &#8211; to target the first child descendant element that matches the given CSS selector</li>
</ul>



<p>As a proof, let&#8217;s take a look at what happened previously: </p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="345" height="137" src="http://blog.codersee.com/wp-content/uploads/2025/03/image-4.png" alt="" class="wp-image-18512871" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/image-4.png 345w, https://blog.codersee.com/wp-content/uploads/2025/03/image-4-300x119.png 300w" sizes="auto, (max-width: 345px) 100vw, 345px" /></figure>



<p>As we can see, the table row was inserted inside the <code>form</code>. And that does not make sense, at all. </p>



<p>So, to fix that, let&#8217;s target the <code>table tbody</code> instead: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun FlowContent.insertUserForm() {
    div {
        form {
            attributes["hx-post"] = "/users"
            attributes["hx-target"] = "#users-table"</pre>



<p>As a result, all the other rows are deleted, but it seems to be closer to what we want:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="379" height="249" src="http://blog.codersee.com/wp-content/uploads/2025/03/image-5.png" alt="" class="wp-image-18512872" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/image-5.png 379w, https://blog.codersee.com/wp-content/uploads/2025/03/image-5-300x197.png 300w" sizes="auto, (max-width: 379px) 100vw, 379px" /></figure>



<h3 class="wp-block-heading" id="h-swapping-in-htmx">Swapping in htmx</h3>



<p><strong>Next lesson:</strong> by default, <strong>htmx replaces the innerHTML of the target element</strong>. </p>



<p>So, in our case, the user was added successfully. We can even refresh the page and see that the array contains all created users. However, we have not defined the <code>hx-swap</code> so the <code>tbody</code> inner HTML was deleted, and our returned one was inserted instead. </p>



<p>So, we must add the <code>hx-swap</code> with one of the following values:</p>



<ul class="wp-block-list">
<li><code>innerHTML</code>&#8211; puts the content inside the target element</li>



<li><code>outerHTML</code>&#8211; replaces the entire target element with the returned content</li>



<li><code>afterbegin</code>&#8211; prepends the content before the first child inside the target</li>



<li><code>beforebegin</code>&#8211; prepends the content before the target in the target’s parent element</li>



<li><code>beforeend</code>&#8211; appends the content after the last child inside the target</li>



<li><code>afterend</code>&#8211; appends the content after the target in the target’s parent element</li>



<li><code>delete</code>&#8211; deletes the target element regardless of the response</li>



<li><code>none</code>&#8211; does not append content from response (Out of Band Swaps and Response Headers will still be processed)</li>
</ul>



<p>And in our case, the <code>beforeend</code> is the one we should pick to append the created user at the end of the list:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun FlowContent.insertUserForm() {
    div {
        form {
            attributes["hx-post"] = "/users"
            attributes["hx-target"] = "#users-table"
            attributes["hx-swap"] = "beforeend"</pre>



<p>When we restart the app, everything works fine! 🙂 </p>



<h3 class="wp-block-heading" id="h-dynamic-htmx-tags-in-kotlin">Dynamic htmx Tags in Kotlin</h3>



<p>At this point, we know how to display and add new users with htmx. So, let&#8217;s learn how to delete them.</p>



<p>As the first step, let&#8217;s prepare a Ktor handler inside the <code>route("/users")</code> for the DELETE request:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">delete("/{id}") {
    val id = call.parameters["id"]!!
    userRepository.delete(id)
    call.respond(HttpStatusCode.OK)
}</pre>



<p>With that code, whenever a <code>DELETE /users/{some-id}</code> is made, we remove the user from our list and return 200 OK.</p>



<p><strong>Important lesson here:</strong> for simplicity, we return <code>200 OK</code> (and not <code>204 No Content</code>), because by default, htmx ignores successful responses other than 200.</p>



<p>Following, let&#8217;s update our button: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">td {
        button {
            attributes["hx-delete"] = "/users/${user.id}"
            attributes["hx-swap"] = "outerHTML"
            attributes["hx-target"] = "closest tr"</pre>



<p>So, firstly, whenever we generate our button, we use <strong>Kotlin string interpolation</strong> to put the user identifier in the <code>hx-delete</code> attribute value. A neat and easy way to achieve that with Kotlin. </p>



<p>When it comes to swapping, we want to find the closest <code>tr</code> parent and swap the entire element with the response. And as the response contains <strong>nothing</strong>, it will be simply removed😉</p>



<p>After we rerun the application, we will see everything working perfectly fine!</p>



<h3 class="wp-block-heading" id="h-error-handling-with-ktor-and-htmx">Error Handling with Ktor and htmx</h3>



<p>Following, let&#8217;s learn how we can handle any Ktor error response in htmx. </p>



<p>For that purpose, let&#8217;s update the POST handler in Ktor:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">post {
    val formParams = call.receiveParameters()
    val firstName = formParams["first-name"]!!
    val lastName = formParams["last-name"]!!
    val enabled = formParams["enabled-radio"]!!.toBoolean()
    if (firstName.isBlank() || lastName.isBlank())
        return@post call.respond(HttpStatusCode.BadRequest)
... the rest of the code</pre>



<p>With that validation, whenever <code>first-name</code> or <code>last-name</code> form parameter is blank, the API client receives <code>400 Bad Request</code>.</p>



<p>After we restart the server and try to make a request without passing first or last name, we see that nothing is happening. No pop-ups, alerts, nothing. The only indication that the request is actually made is thenetwork tab of our browser.</p>



<p>Well, unfortunately (or fortunately?), htmx does not provide any handling out-of-the-box.</p>



<p>But, it throws two events:</p>



<ul class="wp-block-list">
<li><code>htmx:responseError</code>&#8211; in the event of an error response from the server, like <code>400 Bad Request</code></li>



<li><code>htmx:sendError</code>&#8211; in case of connection error</li>
</ul>



<p>So, let&#8217;s add a tiny bit of JS in Kotlin, then: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private fun BODY.insertErrorHandlingScripts() {
    script {
        +"""
            document.body.addEventListener('htmx:responseError', function(evt) {
              alert('An error occurred! HTTP status:' + evt.detail.xhr.status);
            });
            
            document.body.addEventListener('htmx:sendError', function(evt) {
              alert('Server unavailable!');
            });
        """.trimIndent()
    }
}</pre>



<p>And let&#8217;s add this script at the end of the body when rendering the homepage:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    head {
        script {
            src = "https://unpkg.com/htmx.org@2.0.4"
        }
    }
    body {
        div {
            insertHeader()
            insertUserForm()
            insertUserTable(userRepository.findAll())
        }
        insertErrorHandlingScripts()
    }
}</pre>



<p>Excellent! From now on, whenever the API client receives an error response, the alert is displayed. Moreover, if we turn off our server, we will see the error response, too.</p>



<p>And basically, that is all for the htmx part with Kotlin. From now on, we are going to work on the styling of our application😉</p>



<h2 class="wp-block-heading" id="h-returning-images-in-ktor">Returning Images in Ktor</h2>



<p>Before we head to the Tailwind CSS part, let&#8217;s learn one more thing in Ktor: static responses handling.</p>



<p>So, let&#8217;s put the below image in the <code>resources -&gt; img</code> directory:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="500" height="500" src="http://blog.codersee.com/wp-content/uploads/2025/03/placeholder.png" alt="Image is a placeholder used ad an example in our project and shows Codersee logo." class="wp-image-18512878" style="width:100px" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/placeholder.png 500w, https://blog.codersee.com/wp-content/uploads/2025/03/placeholder-300x300.png 300w, https://blog.codersee.com/wp-content/uploads/2025/03/placeholder-150x150.png 150w" sizes="auto, (max-width: 500px) 100vw, 500px" /></figure>



<p>And let&#8217;s add this image as a placeholder to each row in our table: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun TR.insertUserRowCells(user: User) {
    td {
        div {
            img {
                src = "/img/placeholder.png"
            }</pre>



<p>When we rerun the application, we can see that it does not work.</p>



<p>Well, to fix that, we must instruct Ktor to serve our resources as static content:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun Application.configureRouting(userRepository: UserRepository) {
    routing {
        staticResources("/img", "img")</pre>



<p>This time, when we restart the application, we see that placeholders are working fine. </p>



<p>And we will style them in a moment 😉 </p>



<h2 class="wp-block-heading" id="h-styling-with-tailwind-css">Styling With Tailwind CSS</h2>



<p>At this point, we have a fully working Kotlin and htmx integration.</p>



<p>So, if we already did something else than the JSON response, let&#8217;s make it nice😄</p>



<h3 class="wp-block-heading" id="h-import-tailwind">Import Tailwind</h3>



<p>Just like with htmx, let&#8217;s use the CDN to import Tailwind to the project:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    head {
        script {
            src = "https://unpkg.com/htmx.org@2.0.4"
        }
        script {
            src = "https://unpkg.com/@tailwindcss/browser@4"
        }
    }</pre>



<h3 class="wp-block-heading" id="h-update-index">Update Index </h3>



<p>Then, let&#8217;s navigate to the <code>Index.kt</code> and add adjustments:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun HTML.renderIndex(userRepository: UserRepository) {
    head {
        script {
            src = "https://unpkg.com/htmx.org@2.0.4"
        }
        script {
            src = "https://unpkg.com/@tailwindcss/browser@4"
        }
    }
    body {
        div {
            classes = setOf("m-auto max-w-5xl w-full overflow-hidden")
            insertHeader()
            insertUserForm()
            insertUserTable(userRepository.findAll())
        }
        insertErrorHandlingScripts()
    }
}
private fun FlowContent.insertHeader() {
    h5 {
        classes =
            setOf("py-8 block font-sans text-xl antialiased font-semibold leading-snug tracking-normal text-blue-gray-900")
        +"Users list"
    }
}
private fun BODY.insertErrorHandlingScripts() {
    script {
        +"""
            document.body.addEventListener('htmx:responseError', function(evt) {
              alert('An error occurred! HTTP status:' + evt.detail.xhr.status);
            });
            
            document.body.addEventListener('htmx:sendError', function(evt) {
              alert('Server unavailable!');
            });
        """.trimIndent()
    }
}</pre>



<p>As we can see, we can use the <code>classes</code> in Kotlin HTML DSL to prive classes names as a Set of String values:</p>



<p>classes = setOf(&#8220;m-auto max-w-5xl w-full overflow-hidden&#8221;)</p>



<p>In my case, I prefer simply copy-pasting those values instead of separating them with colons.</p>



<h2 class="wp-block-heading" id="h-refactor-form">Refactor Form</h2>



<p>Then, let&#8217;s update the <code>Form.kt</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun FlowContent.insertUserForm() {
    div {
        classes = setOf("mx-auto w-full")
        form {
            attributes["hx-post"] = "/users"
            attributes["hx-target"] = "#users-table"
            attributes["hx-swap"] = "beforeend"
            div {
                classes = setOf("-mx-3 flex flex-wrap")
                div {
                    classes = setOf("w-full px-3 sm:w-1/4")
                    label {
                        classes = setOf("mb-3 block text-base font-medium text-[#07074D]")
                        htmlFor = "first-name"
                        +"First Name"
                    }
                    input {
                        classes =
                            setOf("w-full rounded-md border border-[#e0e0e0] bg-white py-3 px-6 text-base font-medium text-[#6B7280] outline-none focus:border-[#6A64F1] focus:shadow-md")
                        type = InputType.text
                        name = "first-name"
                        id = "first-name"
                        placeholder = "First Name"
                    }
                }
                div {
                    classes = setOf("w-full px-3 sm:w-1/4")
                    label {
                        classes = setOf("mb-3 block text-base font-medium text-[#07074D]")
                        htmlFor = "last-name"
                        +"Last Name"
                    }
                    input {
                        classes =
                            setOf("w-full rounded-md border border-[#e0e0e0] bg-white py-3 px-6 text-base font-medium text-[#6B7280] outline-none focus:border-[#6A64F1] focus:shadow-md")
                        type = InputType.text
                        name = "last-name"
                        id = "last-name"
                        placeholder = "Last Name"
                    }
                }
                div {
                    classes = setOf("w-full px-3 sm:w-1/4")
                    label {
                        classes = setOf("mb-3 block text-base font-medium text-[#07074D]")
                        +"Account enabled"
                    }
                    div {
                        classes = setOf("flex items-center space-x-6 pt-3")
                        div {
                            classes = setOf("flex items-center")
                            input {
                                classes = setOf("h-5 w-5")
                                type = InputType.radio
                                name = "enabled-radio"
                                id = "radio-button-1"
                                value = "true"
                            }
                            label {
                                classes = setOf("pl-3 text-base font-medium text-[#07074D]")
                                htmlFor = "radio-button-1"
                                +"Yes"
                            }
                        }
                        div {
                            classes = setOf("flex items-center")
                            input {
                                classes = setOf("h-5 w-5")
                                type = InputType.radio
                                name = "enabled-radio"
                                id = "radio-button-2"
                                value = "false"
                                checked = true
                            }
                            label {
                                classes = setOf("pl-3 text-base font-medium text-[#07074D]")
                                htmlFor = "radio-button-2"
                                +"No"
                            }
                        }
                    }
                }
                div {
                    classes = setOf("w-full px-3 sm:w-1/4 pt-8")
                    button {
                        classes =
                            setOf("cursor-pointer rounded-md bg-slate-800 py-3 px-8 text-center text-base font-semibold text-white outline-none")
                        +"Add user"
                    }
                }
            }
        }
    }
}</pre>



<p>Similarly, we don&#8217;t change anything in here apart from adding a bunch of classes. A whooooole bunch of classes 🙂 </p>



<h2 class="wp-block-heading" id="h-modify-user-table">Modify User Table</h2>



<p>As the last step, let&#8217; apply changes to our user table: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun FlowContent.insertUserTable(users: List&lt;User>) {
    div {
        classes = setOf("px-0 overflow-scroll")
        table {
            classes = setOf("w-full mt-4 text-left table-auto min-w-max")
            thead {
                tr {
                    th {
                        classes = setOf("p-4 border-y border-blue-gray-100 bg-blue-gray-50/50")
                        +"User"
                    }
                    th {
                        classes = setOf("p-4 border-y border-blue-gray-100 bg-blue-gray-50/50")
                        +"Status"
                    }
                    th {
                        classes = setOf("p-4 border-y border-blue-gray-100 bg-blue-gray-50/50")
                        +"Created At"
                    }
                    th {
                        classes = setOf("p-4 border-y border-blue-gray-100 bg-blue-gray-50/50")
                    }
                }
            }
            tbody {
                id = "users-table"
                users.forEach { user ->
                    tr {
                        insertUserRowCells(user)
                    }
                }
            }
        }
    }
}
fun TR.insertUserRowCells(user: User) {
    td {
        classes = setOf("p-4 border-b border-blue-gray-50")
        div {
            classes = setOf("flex items-center gap-3")
            img {
                classes = setOf("relative inline-block h-9 w-9 !rounded-full object-cover object-center")
                src = "/img/placeholder.png"
            }
            p {
                classes = setOf("block font-sans text-sm antialiased font-normal leading-normal text-blue-gray-900")
                +"${user.firstName} ${user.lastName}"
            }
        }
    }
    td {
        classes = setOf("p-4 border-b border-blue-gray-50")
        div {
            classes = setOf("w-max")
            div {
                val enabledLabel = if (user.enabled) "Enabled" else "Disabled"
                val labelColor = if (user.enabled) "green" else "red"
                classes =
                    setOf("relative grid items-center px-2 py-1 font-sans text-xs font-bold text-black-900 uppercase rounded-md select-none whitespace-nowrap bg-$labelColor-500/20")
                span { +enabledLabel }
            }
        }
    }
    td {
        classes = setOf("p-4 border-b border-blue-gray-50")
        p {
            classes = setOf("block font-sans text-sm antialiased font-normal leading-normal text-blue-gray-900")
            +user.createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
        }
    }
    td {
        classes = setOf("p-4 border-b border-blue-gray-50")
        button {
            classes =
                setOf("cursor-pointer relative h-10 max-h-[40px] w-10 max-w-[40px] select-none rounded-lg text-center align-middle font-sans text-xs font-medium uppercase text-gray-900 transition-all hover:bg-gray-900/10 active:bg-gray-900/20 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none")
            attributes["hx-delete"] = "/users/${user.id}"
            attributes["hx-swap"] = "outerHTML"
            attributes["hx-target"] = "closest tr"
            unsafe {
                +"""
                    &lt;span class="absolute transform -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2">
                        &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
                             stroke-width="2" stroke="currentColor" class="w-6 h-6">
                            &lt;path stroke-linecap="round" stroke-linejoin="round"
                                  d="M6 18L18 6M6 6l12 12"/>
                        &lt;/svg>
                    &lt;/span>
                """.trimIndent()
            }
        }
    }
}</pre>



<p>And here, apart from the CSS classes, we also added the <code>X</code> icon with the <code>unsafe</code> function from Kotlin HTML DSL:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">unsafe {
    +"""
        &lt;span class="absolute transform -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2">
            &lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
                 stroke-width="2" stroke="currentColor" class="w-6 h-6">
                &lt;path stroke-linecap="round" stroke-linejoin="round"
                      d="M6 18L18 6M6 6l12 12"/>
            &lt;/svg>
        &lt;/span>
    """.trimIndent()
}</pre>



<p>And voila! When we run the application now, we should see a pretty decent-looking UI😉</p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>That&#8217;s all for this tutorial on how to work with htmx and Kotlin HTML DSL in Ktor.</p>



<p>Again, if you are tired of wasting your time looking for good Ktor resources, then check out my <a href="https://codersee.com/courses/ktor-server-pro/">Ktor Server Pro course</a>:</p>



<p>▶️ Over 15 hours of video content divided into over 130 lessons</p>



<p>🛠️ Hands-on approach: together, we implement 4 actual services</p>



<p>✅ top technologies: you will learn not only Ktor, but also how to integrate it with modern stack including JWT, PostgreSQL, MySQL, MongoDB, Redis, and Testcontainers.</p>



<p>Lastly, you can find the source code for this lesson in <a href="https://github.com/codersee-blog/ktor-htmx" target="_blank" rel="noreferrer noopener">this GitHub repository</a>.</p>
<p>The post <a href="https://blog.codersee.com/quick-quide-to-htmx-kotlin/">A Quick Guide to htmx in Kotlin</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/quick-quide-to-htmx-kotlin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MockK with Coroutines [5/5]</title>
		<link>https://blog.codersee.com/mockk-coroutines/</link>
					<comments>https://blog.codersee.com/mockk-coroutines/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 04 Mar 2025 17:55:48 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=17512712</guid>

					<description><![CDATA[<p>In the last article in a series, we are going to learn everything we need to know to work with MockK and Kotlin coroutines. </p>
<p>The post <a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>At this point, we spent a lot of time exploring MockK features and syntax, so at this point, adding coroutines will be trivial, trust me😉</p>



<p>Of course, you can find the rest of the series on my blog, too:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li>MockK with Coroutines [5/5]</li>
</ul>



<h2 class="wp-block-heading" id="h-video-content">Video Content</h2>



<p>As always, if you prefer a video content, then please check out my latest YouTube video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/mockk-coroutines/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FW0nnZl4R6C0%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-additional-imports">Additional Imports</h2>



<p>As the first step, let&#8217;s add the necessary import:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.1")</pre>



<p>This package provides utilities for testing coroutines.</p>



<p>And thanks to that, we can mock and test suspend functions.</p>



<h2 class="wp-block-heading">Code To Test</h2>



<p>Following, let&#8217;s introduce the suspended functions:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Eight(
    private val one: EightOne,
    private val two: EightTwo,
) {
    suspend fun funToTest(): String {
        return "${one.returnInt()} ${two.returnString()}"
    }
}

class EightOne {
    suspend fun returnInt(): Int = 10
}

class EightTwo {
    suspend fun returnString(): String = "Some String"
}</pre>



<p>And I know it does not make sense. But it is not important here😉</p>



<p>The important part is that we have suspended functions so we can start implementing tests.</p>



<h2 class="wp-block-heading">MockK with Coroutines</h2>



<p>As the next step, let&#8217;s try to implement the test &#8220;the old way&#8221;:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class EightTest {
    private val one: EightOne = mockk()
    private val two: EightTwo = mockk()

    private val eight = Eight(one, two)

    @Test
    fun `should return 1 codersee`() {
        every { one.returnInt() } returns 1
        every { two.returnString() } returns "codersee"

        val result = eight.funToTest()

        assertEquals("1 codersee", result)

        verifySequence {
            one.returnInt()
            two.returnString()
        }
    }
}</pre>



<p>As a result, we can see the compiler complaining about our suspended functions:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Suspend function 'returnInt' should be called only from a coroutine or another suspend function
Suspend function 'returnString' should be called only from a coroutine or another suspend function
Suspend function 'funToTest' should be called only from a coroutine or another suspend function</pre>



<p>So, as the first step, let&#8217;s add the <code>runTest</code> to get rid of the last error:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 1 codersee`() = runTest {</pre>



<p>The <code>runTest</code> is not related to the MockK itself. It comes from <code>kotlinx.coroutines</code> and executes our test body in a new coroutine, returning <code>TestResult</code> .</p>



<p>When it comes to MockK, then we can work with coroutines and suspended functions by simply adding the &#8220;co&#8221; suffix for all functions:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class EightTest {
    private val one: EightOne = mockk()
    private val two: EightTwo = mockk()

    private val eight = Eight(one, two)

    @Test
    fun `should return 1 codersee`() = runTest {
        coEvery { one.returnInt() } returns 1
        coEvery { two.returnString() } returns "codersee"

        val result = eight.funToTest()

        assertEquals("1 codersee", result)

        coVerifySequence {
            one.returnInt()
            two.returnString()
        }
    }
}</pre>



<p>And yes, this is that easy!😉</p>



<p>MockK comes with plenty of functions to work with suspend functions, like:</p>



<ul class="wp-block-list">
<li><code>coVerify</code></li>



<li><code>coEvery</code></li>



<li><code>coJustRun</code></li>



<li><code>coJustAwait</code></li>



<li><code>coAnswers</code></li>



<li>and many more😉</li>
</ul>



<h2 class="wp-block-heading">Issue With Spies</h2>



<p>Lastly, at the moment of writing, there is one issue with spies and coroutines in MockK. You can see all the details here: <a href="https://github.com/mockk/mockk/issues/554">https://github.com/mockk/mockk/issues/554</a></p>



<p>Assuming this is quite an old one, I wouldn&#8217;t expect it to be fixed in the near future.</p>



<p>But if that is the case, then please let me know in the comments below.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>That&#8217;s all for this series about MockK &#8211; the mocking library for Kotlin.</p>



<p>During our time together, we learned A LOT, and I believe you are ready to use it in your projects!</p>



<p>Let me know your thoughts in the comments below, and if you are looking for the other articles, then here you are:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li>MockK with Coroutines [5/5]</li>
</ul>
<p>The post <a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/mockk-coroutines/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MockK: Spy, Relaxed Mock, and Partial Mocking [4/5]</title>
		<link>https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/</link>
					<comments>https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 04 Mar 2025 17:55:42 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=17512701</guid>

					<description><![CDATA[<p>In the fourth artcile in a series, we are going to learn what are MockK spies, relaxed mocks and how to do a partial mocking.</p>
<p>The post <a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spy, Relaxed Mock, and Partial Mocking [4/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>At this point, we know quite a lot about mocks, verification, and how to perform stubbings. In this lesson, we are going to expand our horizons and see additional features useful in day-to-day scenarios, like relaxed mocks.</p>



<p>Of course, you can find the rest of the series on my blog, too:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="MockK: Objects, Top-Level, and Extension Functions [3/5]">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li>MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<h2 class="wp-block-heading" id="h-video-content">Video Content</h2>



<p>As always, if you prefer a video content, then please check out my latest YouTube video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FyukKpPr_iBg%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-mockk-relaxed-mock">MockK: Relaxed Mock</h2>



<p>What does a <strong>relaxed mock</strong> mean?</p>



<p>Well, long story short, it is <strong>a mock that returns some value for all functions</strong>. In other words, the value is returned even if we do not provide a stubbing.</p>



<p>To better understand, let&#8217;s take a look at the example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Five(
    private val one: FiveOne,
) {
    fun funToTest(): String {
        one.returnInt()
        return one.returnString()
    }
}

class FiveOne {
    fun returnInt(): Int = 10
    fun returnString(): String = "Some String"
}</pre>



<p>As we can see, the function we want to test invokes two another: <code>returnInt</code> and <code>returnString</code>.</p>



<p>And I am pretty sure that at this point, you know the result without even running the test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class FiveTest {

    private val one: FiveOne = mockk()
    private val five = Five(one)

    @Test
    fun `should return mocked string`() {
        every { one.returnString() } returns "mocked"

        val result = five.funToTest()

        assertEquals("mocked", result)
    }
}</pre>



<p>That&#8217;s right, it fails, and MockK complains about missing answer:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">no answer found for FiveOne(#1).returnInt() among the configured answers: (FiveOne(#1).returnString()))
io.mockk.MockKException: no answer found for FiveOne(#1).returnInt() among the configured answers: (FiveOne(#1).returnString()))</pre>



<p>And as you may have guessed, a relaxed mock may help us here a bit. But how do we define it in MockK?</p>



<p>It&#8217;s easy; the only thing we need is to set up the <code>relaxed</code> flag on creation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private val one: FiveOne = mockk(relaxed = true)</pre>



<p>(When working with annotations, we can use <code>@RelaxedMockK</code> instead of <code>@MockK</code>)</p>



<p>So, now, when we repeat our test, <strong>it passes!</strong></p>



<p>Moreover, we could even completely skip the stubbing part:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return empty string`() {
    val result = five.funToTest()

    assertEquals("", result)
}</pre>



<p>But please don&#8217;t do that in your tests and treat them as a curiosity😉</p>



<p>And before we head to the next part, I just wanted to mention that <strong>for Unit-returning functions, we must set a separate flag- </strong><code><strong>relaxUnitFun</strong></code><strong> &#8211; to true:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private val one: FiveOne = mockk(relaxed = true, relaxUnitFun = true)</pre>



<h2 class="wp-block-heading">Partial Mocking</h2>



<p>Nextly, let&#8217;s focus on the <strong>partial mocking.</strong></p>



<p>This technique, on the other hand, allows us to <strong>invoke the actual function</strong>.</p>



<p>Let&#8217;s take a look at the example of a new class to test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Six(
    private val one: SixOne,
) {
    fun funToTest(): String {
        one.returnInt()
        return one.returnString()
    }
}

class SixOne {
    fun returnInt(): Int = 10
    fun returnString(): String = "Some String"
}</pre>



<p>As we can see, apart from the names, it works exactly the same as previously.</p>



<p>So, let&#8217;s take a look at the test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class SixTest {

    private val one: SixOne = mockk()
    private val five = Six(one)

    @Test
    fun `should invoke actual functions`() {
        every { one.returnInt() } answers { callOriginal() }
        every { one.returnString() } answers { callOriginal() }

        val result = five.funToTest()

        assertEquals("Some String", result)
    }
}</pre>



<p>As we can see, in MockK, we can use the <code>answers { callOriginal() }</code>&nbsp; to invoke the actual function. And that&#8217;s why we get <em>&#8220;Some String&#8221;</em> value here.</p>



<h2 class="wp-block-heading">MockK Spy</h2>



<p>As the last step, let&#8217;s take a look at the <strong>spies</strong>. What are they?</p>



<p>Well, they are a mix of real objects with mocks. Whenever we do not specify any stubbing, the actual function is invoked.</p>



<p>So, the main difference between spies and partial mocking is that for a spy, the original function is invoked if we don&#8217;t write anything. In partial mocking, we must be explicit.</p>



<p>Let&#8217;s take a look at the code to test then. Again, this is a 1:1 copy of previous examples:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Seven(
    private val one: SevenOne,
) {
    fun funToTest(): String {
        one.returnInt()
        return one.returnString()
    }
}

class SevenOne {
    fun returnInt(): Int = 10
    fun returnString(): String = "Some String"
}</pre>



<p>Following, let&#8217;s implement a simple test with a MockK spy then:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class SevenTest {

    private val one: SevenOne = spyk(SevenOne())

    private val five = Seven(one)

    @Test
    fun `should invoke actual functions`() {
        val result = five.funToTest()

        assertEquals("Some String", result)
    }
}</pre>



<p>And we can see the interesting difference here- we pass the instance of the dependent object to the <code>spyk</code> . And although underneath a copy of that object will be used rather than the passed instance, this shows that <strong>spies are actual objects with mocking capabilities.</strong></p>



<p>Additionally, we can use a similar notation to <code>mockk</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private val one: SevenOne = spyk()
// or 
private val one = spyk&lt;SevenOne>()</pre>



<p>In this case, the default constructor will be invoked.</p>



<p>And if you are wondering when to use spies, and when to choose partial mocks, then I would say that partial mocks will be better whenever actual calls are rare, almost exceptional. If since the very beginning we want to mix actual resposnes with stubs, then spies will be more optiomal option.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>That&#8217;s all for the fourth article in a series in which we learned how to deal with MockK spies, relaxed mocks, and partial mocking.</p>



<p>Awesome! And without any further ado, let&#8217;s head to the next lesson:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="MockK: Objects, Top-Level, and Extension Functions [3/5]">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li>MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<p></p>
<p>The post <a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spy, Relaxed Mock, and Partial Mocking [4/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MockK: Objects, Top-Level, and Extension Functions [3/5]</title>
		<link>https://blog.codersee.com/mockk-objects-top-level-extension-functions/</link>
					<comments>https://blog.codersee.com/mockk-objects-top-level-extension-functions/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 04 Mar 2025 17:55:29 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=17512691</guid>

					<description><![CDATA[<p>In the third artcile in a series, we are going to focus on Kotlin objects, top-level and extension functions in MockK. </p>
<p>The post <a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<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>



<p>Of course, you can find the rest of the series on my blog, too:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li>MockK: Objects, Top-Level, and Extension Functions [3/5]</li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<h2 class="wp-block-heading" id="h-video-content">Video Content</h2>



<p>As always, if you prefer a video content, then please check out my latest YouTube video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FaesDHmuny_0%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-kotlin-objects-and-mockk">Kotlin Objects and MockK</h2>



<p>Let&#8217;s start everything by explaining <strong>how to mock Kotlin objects in MockK</strong>.</p>



<p>And as you know, objects are pretty specific, so we are going to see two, different examples and approaches.</p>



<h3 class="wp-block-heading" id="h-mockkobject"><code>mockkObject</code></h3>



<p>Let&#8217;s introduce a simple example with an object:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class One {
    fun funToTest(): UUID = SomeObject.generateId()
}

object SomeObject {
    fun generateId(): UUID = UUID.randomUUID()
}</pre>



<p>It is not rocket science, right? We are going to simply test the function that should return the UUID generated by <code>SomeObject</code> function.</p>



<p>So, if we would like to mock that UUID to gain more control over the behavior, then we can use the <code>mockkObject</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class OneTest {

    private val one = One()

    @Test
    fun `should return mocked ID`() {
        val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

        mockkObject(SomeObject)
        every { SomeObject.generateId() } returns id

        val result = one.funToTest()

        assertEquals(id, result)
    }
}</pre>



<p>The above test succeeds, and we can see that we define stubbing just like with every mock.</p>



<p>Moreover, if we add <code>mockkObject</code> inside the function, it will not affect the scope of other tests:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class OneTest {

    private val one = One()

    @Test
    fun `should return mocked ID`() {
        val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

        mockkObject(SomeObject)
        every { SomeObject.generateId() } returns id

        val result = one.funToTest()

        assertEquals(id, result)
    }

    @Test
    fun `should fail returning mocked ID`() {
        val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

        val result = one.funToTest()

        assertEquals(id, result)
    }
}</pre>



<p>This time, the second test fails because <code>SomeObject</code> returns a <strong>random value.</strong></p>



<p>Additionally, if we use the <code>mockkObject</code> , but we don&#8217;t provide stubbing, <strong>MockK will not throw any exception:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should fail returning mocked ID`() {
    val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    mockkObject(SomeObject)
    val result = one.funToTest()

    assertEquals(id, result)
}</pre>



<p>The above test runs just like <code>mockkObject(SomeObject)</code> does not exist. As a result, we get a random UUID.</p>



<p>So, we must be cautious about that.</p>



<h3 class="wp-block-heading"><code>unmockkObject</code></h3>



<p>Although I highly doubt we should ever use that, MockK allows us to &#8220;unmock&#8221; the object with <code>unmockkObject</code> function.</p>



<p>How does it work?</p>



<p>Let&#8217;s analyze the below snippet:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should illustrate unmockkObject`() {
    val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    mockkObject(SomeObject)
    every { SomeObject.generateId() } returns id

    assertEquals(id, one.funToTest())

    unmockkObject(SomeObject)
    assertEquals(id, one.funToTest())
}</pre>



<p>In this example, the first assertion succeeds. However, the second <code>assertEquals</code> fails due to <code>unmockkObject</code> that reverts our mock.</p>



<p>So, again, during the second call, a random UUID is generated.</p>



<h3 class="wp-block-heading">Create Mock Object Instance</h3>



<p>I know, this title sounds simply weird.</p>



<p>Nevertheless, let&#8217;s take a look at another class- <code>Two</code> :</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Two(
    private val someObject: SomeObject,
) {
    fun funToTest(): UUID = someObject.generateId()
}</pre>



<p>This time, we inject our <code>SomeObject</code> through the constructor.</p>



<p>And for consistency, in MockK, we can mock that just like a simple class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class TwoTest {

    private val someObject = mockk&lt;SomeObject>()
    private val two = Two(someObject)

    @Test
    fun `should return mocked ID`() {
        val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

        every { someObject.generateId() } returns id

        val result = two.funToTest()

        assertEquals(id, result)
    }
}</pre>



<p>But, <strong>we must remember about two, important things in this case.</strong></p>



<p>Firstly, we <strong>must provide a stubbing</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should fail due to missing stubbing`() {
    val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    val result = two.funToTest()

    assertEquals(id, result)
}</pre>



<p>So, just like with classes, the above test fails due to missing stubbing!</p>



<p>Secondly, when defining stubbing, we <strong>must use the instance</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should fail due to incorrect stubbing`() {
    val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    every { SomeObject.generateId() } returns id

    val result = two.funToTest()

    assertEquals(id, result)
}</pre>



<p>As we can see, we cannot refer to the <code>SomeObject</code> anymore.</p>



<p>So, as always, the choice is up to you. 🙂</p>



<h2 class="wp-block-heading">MockK and Top-Level Functions</h2>



<p>With all of that said about objects, let&#8217;s take a look at how we can deal with another Kotlin feature, <strong>top-level functions</strong>, in MockK.</p>



<p>As the first step, let&#8217;s take a look at the code to test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Three {
    fun funToTest(): UUID = generateId()
}

fun generateId(): UUID = UUID.randomUUID()</pre>



<p>This time, instead of the object and its function, we&#8217;re dealing with top-level <code>generateId</code> .</p>



<p>And from the MockK perspective, everything looks pretty much the same as with objects:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class ThreeTest {

    private val three = Three()

    @Test
    fun `should return mocked ID`() {
        val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

        mockkStatic(::generateId)
        every { generateId() } returns id

        val result = three.funToTest()

        assertEquals(id, result)
    }
}</pre>



<p>As we can see, we use the <code>mockkStatic</code> and we simply provide our stubbing.</p>



<p>And just like in the first approach in objects, nothing happens if we define the <code>mockkStatic</code> , but we don&#8217;t set the stubbing. The random UUID is generated:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should fail due to missing stubbing`() {
    val id = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    mockkStatic(::generateId)

    val result = three.funToTest()

    assertEquals(id, result)
}</pre>



<p>Lastly, I just wanted to mention that we have a similar function- <code>clearStaticMockk</code>&#8211; on the table, too😉</p>



<h2 class="wp-block-heading">Extension Functions Support</h2>



<p>As the last thing in this article, let&#8217;s take a look at the example leveraging the extension function:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Four {
    fun funToTest(): String = "abc".withCustomCase()
}

fun String.withCustomCase(): String = this.uppercase()</pre>



<p>It does not make too much sense, but we can clearly see that our extension function should return an uppercase String value.</p>



<p>And to mock this case in MockK, we can use <code>mockkStatic</code> once again:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class FourTest {

    private val four = Four()

    @Test
    fun `should return codersee`() {
        mockkStatic(String::withCustomCase)
        every { "abc".withCustomCase() } returns "codersee"
        every { "xyz".withCustomCase() } returns "not-codersee"

        val result = four.funToTest()

        assertEquals("codersee", result)
    }
}</pre>



<p>The really interesting part in the above snippet is that the String value <strong>must match!</strong></p>



<p>Additionally, MockK allows us to mock extension functions defined in a class.</p>



<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="noreferrer noopener">here</a>.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>That&#8217;s all for the third article, in which we learned how to deal with Kotlin objects, top-level and extension functions in MockK.</p>



<p>Great job, and without any further ado, let&#8217;s head to the next lesson:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li>MockK: Objects, Top-Level, and Extension Functions [3/5]</li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>
<p>The post <a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/mockk-objects-top-level-extension-functions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Verification in MockK [2/5]</title>
		<link>https://blog.codersee.com/verification-mockk/</link>
					<comments>https://blog.codersee.com/verification-mockk/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 04 Mar 2025 17:55:20 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=17512671</guid>

					<description><![CDATA[<p>In the second article in a MockK Kotlin series, we are going to learn more about various verification techniques.</p>
<p>The post <a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>To be more specific, we are going to work with both <em>verification</em> and <em>capturing</em>&#8211; MockK Kotlin features, allowing us to perform assertions against our mocks.</p>



<p>To view other articles in this series, please take a look at:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li>Verification in MockK [2/5]</li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<h2 class="wp-block-heading" id="h-video-content">Video Content</h2>



<p>As always, if you prefer a video content, then please check out my latest YouTube video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/verification-mockk/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FTVponpWSKGE%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-why-do-we-need-verification">Why Do We Need Verification?</h2>



<p>At this point, you may wonder why we need to do anything else besides what we did previously. We configured mocks, and they worked; we made the necessary assertions. </p>



<p>Then what is the point of anything else?</p>



<p>Well, our logic is pretty clear and <strong>predictable</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun createUser(email: String, password: String): UUID {
    userRepository.findUserByEmail(email)
        ?.let { throw IllegalArgumentException("User with email $email already exists") }

    return userRepository.saveUser(email, password)
        .also { userId ->
            emailService.sendEmail(
                to = email,
                subject = "Welcome to Codersee!",
                body = "Welcome user: $userId."
            )
        }
}</pre>



<p>And by predictable, I mean that we see that every function will be invoked at most 1 time. That no other functions are invoked when we throw the exception. And I do not see any possibility that <code>saveUser</code> somehow would trigger before <code>findUserByEmail</code>.</p>



<p>But sometimes, that&#8217;s not the case.</p>



<p>Sometimes mocks may be invoked a variable number of times depending on some response, right? For example, when we call some user endpoint, we get a list of users, and then we fetch something for each user. </p>



<p>Another time, the order may be affected by the algorithm. And yet another time, it may be simply a spaghetti you inherited from someone else😉</p>



<p>And in a moment, we will learn what exactly we can do in our tests.</p>



<h2 class="wp-block-heading">Verification with <code>eq</code></h2>



<p>Before we head to the actual functions, let me share a first MockK verification tip: <strong>prefer <code>eq</code> matchers wherever possible.</strong></p>



<p>To better visualize, let&#8217;s recap the test example once again:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should throw IllegalArgumentException when user with given e-mail already exists`() {
    val email = "contact@codersee.com"
    val password = "pwd"

    val foundUser = User(UUID.randomUUID(), email, password)
    every { userRepository.findUserByEmail(email) } returns foundUser

    assertThrows&lt;IllegalArgumentException> {
        service.createUser(email, password)
    }
}</pre>



<p>We clearly see that <code>foundUser</code> will be returned only if the <code>findUserByEmail</code> is invoked with <code>contact@codersee.com</code></p>



<p>And this is already a kind of verification. Because if we would use <code>any()</code> , or <code>any&lt;String&gt;()</code> , the test would still pass. However,<strong> it would pass even if our logic sent a password there by mistake!</strong></p>



<p>So I guess you see my point here. For such cases, I would go for <code>eq</code> matcher.</p>



<h2 class="wp-block-heading">Various MockK Verifications</h2>



<p>And with all of that said, we can finally take a look at various, actual verifications in MockK.</p>



<p>For that purpose, let&#8217;s introduce a more dummy example that will help us to focus on the topic without unwanted code:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class A (
    private val b: B,
    private val c: C
) {
    fun funToTest(): Int {
        return 5
    }
}

class B {
    fun funFromB(): Int = 10
}

class C {
    fun funFromC(): String = "Hi!"
}</pre>



<h3 class="wp-block-heading"><code>verify</code></h3>



<p>Let&#8217;s start with the simplest one- <code>verify</code> .</p>



<p>And for that, let&#8217;s update the <code>funToTest</code> and write a simple test for it:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun funToTest(): Int {
    repeat(10) { b.funFromB() }
    repeat(5) { c.funFromC() }
    return 5
}

@Test
fun `should return 5 without any verification`() {
    every { b.funFromB() } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)
}</pre>



<p>When we run the test, it succeeds. Moreover, we can clearly see that we can define stubbing once. Even though functions are invoked multiple times.</p>



<p>With the <code>verify</code> , we can make sure that they were invoked a specific number of times:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verification and confirmation`() {
    every { b.funFromB() } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verify(exactly = 10) { b.funFromB() }
    verify(atLeast = 5) { c.funFromC() }

    confirmVerified(b, c)
}</pre>



<p>We can use <code>exactly</code> , <code>atLeast</code> , <code>atMost</code> &#8211; the choice is up to you.</p>



<p>Additionally, if we would like to set some arbitraty <strong>timeout</strong>, then this is our go-to function.</p>



<h3 class="wp-block-heading"><code>confirmVerified</code></h3>



<p>Moreover, we should use <code>verify</code> in combination with <code>confirmVerified</code> .</p>



<p>This way, we additionally check if our test code verified all invoked functions.</p>



<p>If we get rid of <code>verify(atLeast = 5) { c.funFromC() }</code> and rerun the test, we will see:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Verification acknowledgment failed

Verified call count: 0
Recorded call count: 5


Not verified calls:
1) C(#2).funFromC()
2) C(#2).funFromC()
3) C(#2).funFromC()
4) C(#2).funFromC()
5) C(#2).funFromC()</pre>



<p>So, as we can see, this is a great way to double-check our test assumptions (testing a test?🙂).</p>



<h3 class="wp-block-heading"><code>checkUnnecessaryStub</code></h3>



<p>Speaking of testing the test- we can additionally check if there are no unused stubbings.</p>



<p>For that purpose, let&#8217;s slightly update the example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class A(
    private val b: B,
    private val c: C
) {
    fun funToTest(): Int {
        repeat(10) { b.funFromB(7) }
        repeat(5) { c.funFromC() }
        return 5
    }
}

class B {
    fun funFromB(some: Int): Int = 10
}

class C {
    fun funFromC(): String = "Hi!"
}</pre>



<p>So this time, <code>funFromB</code> will always be invoked with <code>7</code> .</p>



<p>And if we make our test this way:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verification and confirmation`() {
    every { b.funFromB(7) } returns 1
    every { b.funFromB(6) } returns 2 // unwanted
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verify(exactly = 10) { b.funFromB(7) }
    verify(atLeast = 5) { c.funFromC() }

    confirmVerified(b, c)
    checkUnnecessaryStub(b, c)
}</pre>



<p>Then MockK will be complaining a bit:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">1) B(#1).funFromB(eq(6)))
java.lang.AssertionError: Unnecessary stubbings detected.
Following stubbings are not used, either because there are unnecessary or because tested code doesn't call them :

1) B(#1).funFromB(eq(6)))</pre>



<h3 class="wp-block-heading"><code>verifyCount</code></h3>



<p>When it comes to counts, we can use the <code>verifyCount</code> function instead:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verifyCount`() {
    every { b.funFromB(7) } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verifyCount {
        10 * { b.funFromB(7) }
        (4..5) * { c.funFromC() }
    }
    confirmVerified(b, c)
}</pre>



<p>This allows us to achieve an even cleaner test with beautiful Kotlin DSL.</p>



<p>Nevertheless, we still have to invoke <code>confirmVerified</code> separately.</p>



<h3 class="wp-block-heading"><code>verifyAll/verifyOrder/verifySequence</code></h3>



<p>Sometimes, we can use <code>verifyAll</code> , <code>verifyOrder</code> , and <code>verifySequence</code> to make the code slightly cleaner.</p>



<p>The <code>verifyAll</code> checks if all calls happened, but it does not verify the order:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verifyAll`() {
    every { b.funFromB(7) } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verifyAll {
        c.funFromC()
        b.funFromB(7)
    }
}</pre>



<p>So, the above function will work like a charm.</p>



<p>On the other hand, if we use the <code>verifyOrder</code> , it won&#8217;t work anymore, and we will have to provide a valid order:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verifyOrder`() {
    every { b.funFromB(7) } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verifyOrder {
        b.funFromB(7)
        c.funFromC()
    }
}</pre>



<p>Lastly, the <code>verifySequence</code> will work similar to <code>verifyOrder</code> , but it will force us to provide the right amount of times in the right order.</p>



<p>So, to make the test work, we would need to do a small tweak:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 5 with verifySequence`() {
    every { b.funFromB(7) } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verifySequence {
        repeat(10) { b.funFromB(7) }
        repeat(5) { c.funFromC() }
    }
}</pre>



<p>The important thing to mention is that if in our <code>verifyAll</code> or <code>verifySequence</code> block we covered all mocks, then we don&#8217;t need to add <code>confirmVerified</code> .</p>



<p>But, <strong>unfortunately</strong>, this will succeed:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should fail due to missing verification`() {
    every { b.funFromB(7) } returns 1
    every { c.funFromC() } returns ""

    val result = a.funToTest()

    assertEquals(5, result)

    verifySequence {
        repeat(10) { b.funFromB(7) }
    }
}</pre>



<p>And we must guard ourselves with <code>confirmVerified(c)</code> .</p>



<p>However, if we do the <code>b</code> and <code>c</code> check inside. Then the <code>confirmedVerified</code> is not needed anymore.</p>



<h2 class="wp-block-heading">MockK capturing</h2>



<p>Lastly, I would like to show you one more interesting MockK feature useful in verification- the <strong>capturing</strong>.</p>



<p>Let&#8217;s imagine a new function inside the <code>B</code> class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class B {
    fun anotherFunFromB(some: Int) {}
}</pre>



<p>Now, the <code>anotherFunToTest</code> invokes it using the random value:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun anotherFunToTest(): Int {
    b.anotherFunFromB(Random.nextInt())
    return 3
}</pre>



<p>So, if we write a test this way:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 3`() {
    justRun { b.anotherFunFromB(any()) }

    val result = a.anotherFunToTest()

    assertEquals(3, result)
}</pre>



<p>We clearly see, that we cannot access this value in any way, right? It is not returned from the function itself. We cannot control it with other mock, too.</p>



<p>Thankfully, we can introduce a <strong>slot </strong>and capture the value on the fly:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return 3`() {
    val randomSlot = slot&lt;Int>()

    justRun { b.anotherFunFromB(capture(randomSlot)) }

    val result = a.anotherFunToTest()

    println("Random value: ${randomSlot.captured}")
    assertEquals(3, result)
}</pre>



<p>This way, the stubbing works just like <code>any()</code> ,but additionally, we can access the random value with <code>captured</code> .</p>



<p>And although this may not be a clear verification, in some cases, it can be really helpful.</p>



<h3 class="wp-block-heading">Summary</h3>



<p>That&#8217;s all for this article about verification in MockK.</p>



<p>We covered various approaches, techniques, and at this point I am pretty sure you will be able to pick the right one for your test cases.</p>



<p>Without any further ado, let&#8217;s head to the next article in this series:</p>



<ul class="wp-block-list">
<li><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a></li>



<li>Verification in MockK [2/5]</li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<p></p>
<p>The post <a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/verification-mockk/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Getting Started with MockK in Kotlin [1/5]</title>
		<link>https://blog.codersee.com/getting-started-with-mockk-kotlin/</link>
					<comments>https://blog.codersee.com/getting-started-with-mockk-kotlin/#comments</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 04 Mar 2025 17:55:01 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Testing]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=17512637</guid>

					<description><![CDATA[<p>In this, first article in a series dedicated to MockK and Kotlin, we will learn how to create mocks, define stubbings and utilize matchers.</p>
<p>The post <a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Before we head there, we will take a quick look at what exactly mocking is, and the differences between several terms that often lead to confusion. Thanks to that, we will have a solid foundation before diving into the <strong>MockK and Kotlin </strong>topics.</p>



<ul class="wp-block-list">
<li>Getting Started with MockK in Kotlin [1/5]</li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>If you enjoy this content, then check out my <a href="https://codersee.com/courses/ktor-server-pro/">Ktor Server PRO</a> course- the most comprehensive Ktor guide in the market. You&#8217;re gonna love it! 🙂 </p>
</blockquote>



<h2 class="wp-block-heading" id="h-video-content">Video Content</h2>



<p>As always, if you prefer a video content, then please check out my latest YouTube video:</p>


<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2F4prbIk2TuX4%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /><figcaption></figcaption></figure>


<h2 class="wp-block-heading" id="h-why-do-we-need-mocking">Why Do We Need Mocking?</h2>



<p>Long story short, we need mocking to isolate the unit / the system under test.</p>



<p>Sounds confusing? No worries.</p>



<p>Let&#8217;s take a look at the typical example of a function:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="576" src="http://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component-1024x576.png" alt="Image is an explainer for MockK and presents a visualization of system under test / unit and dependend on components" class="wp-image-17512639" srcset="https://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component-1024x576.png 1024w, https://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component-300x169.png 300w, https://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component-768x432.png 768w, https://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component-1536x864.png 1536w, https://blog.codersee.com/wp-content/uploads/2025/03/mocking_mockk_system_under_test_dependent_on_component.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>So, our function A- the one we would like to focus on in our test- calls both B and C. It can happen sequentially or simultaneously; it doesn&#8217;t matter.</p>



<p>What matters is that when we want to test A, we want to see its behavior in different cases. How does it behave when B returns (for instance) user data successfully? What happens in case of a null value? Does it handle exceptions gracefully?</p>



<p>And to avoid spending countless hours on manual setup, we use the <strong>mocking </strong>technique to simulate different scenarios. Mostly with the help of libraries, like MockK.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>The important thing to remember is that mocking is not limited to functions. A, B, and C may as well represent services.</p>



<p>And in various sources, A will be referred to as the System Under Test (SUT), whereas B, and C will be Depended On Component (DOC).</p>
</blockquote>



<h2 class="wp-block-heading" id="h-mocking-stubbing-test-doubles">Mocking, Stubbing, Test Doubles</h2>



<p>Frankly, please skip this section if this is your first time with mocking or MockK. I truly believe you will benefit more from focusing on learning MockK-related concepts than slight differences in wording.</p>



<p>Anyway, from the chronicler&#8217;s duty, let me illustrate a few concepts:</p>



<ul class="wp-block-list">
<li><strong>stub </strong>is a fake object that returns hard-coded answers. Typically, we use it to return some value, but we don&#8217;t care about additional info, like how many times it was invoked, etc.</li>



<li><strong>mock</strong> is pretty similar, but this time, we can verify interactions, too. For example, to see if this was invoked with a particular ID value, exactly N times.</li>



<li><strong>stubbing</strong> means setting up a <em>stub</em> or a <em>mock</em> so that a particular method returns some value or throws an exception</li>



<li><strong>mocking</strong> means creating/using a <em>mock</em></li>



<li>and lastly, we use the <strong>test doubles </strong>term for any kind of replacement we use in place of a real object in your tests (that terms comes stund doubles in movies).</li>
</ul>



<p>And if you are looking for a really deep dive, I invite you to <a href="https://martinfowler.com/articles/mocksArentStubs.html" target="_blank" rel="noreferrer noopener">Martin Fowler&#8217;s article</a>.</p>



<h2 class="wp-block-heading" id="h-mockk-imports">MockK Imports</h2>



<p>With all of that said, let&#8217;s head to the practice part. </p>



<p>Firstly, let&#8217;s define the necessary imports for MockK.</p>



<p>We will be working with a plain Kotlin / Gradle project with JUnit 5, so our <code>build.gradle.kts</code> dependencies should look as follows:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">dependencies {
    testImplementation("io.mockk:mockk:1.13.17")
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}</pre>



<p>The <code>io.mockk:mockk</code> is the only thing we need when working with MockK (unless we want to work with couroutines- but I will get back to that in the fifth lesson).</p>



<h2 class="wp-block-heading" id="h-tested-code">Tested Code</h2>



<p>Then, let&#8217;s take a look at the code we are supposed to test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class User(val id: UUID, val email: String, val passwordHash: String)

class UserRepository {
    fun saveUser(email: String, passwordHash: String): UUID =
        UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")

    fun findUserByEmail(email: String): User? =
        User(
            id = UUID.fromString("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"),
            email = "found@codersee.com",
            passwordHash = "foundPwd"
        )
}

class EmailService {
    fun sendEmail(to: String, subject: String, body: String) {
        println("Sending body $body to $to with subject $subject")
    }
}

class UserService(
    private val userRepository: UserRepository,
    private val emailService: EmailService,
) {

    fun createUser(email: String, password: String): UUID {
        userRepository.findUserByEmail(email)
            ?.let { throw IllegalArgumentException("User with email $email already exists") }

        return userRepository.saveUser(email, password)
            .also { userId ->
                emailService.sendEmail(
                    to = email,
                    subject = "Welcome to Codersee!",
                    body = "Welcome user: $userId."
                )
            }
    }
}</pre>



<p>As we can see, we have a simple example of a <code>UserService</code> with one function- <code>createUser</code> . The service and the function that we will focus on in our tests.</p>



<p>And although <code>UserRepository</code> and <code>EmailService</code> look pretty weird, the <code>createUser</code> is more or less something we can find in our real-life code. We check if the given <code>email</code> is taken, and if that&#8217;s the case, we throw an exception. Otherwise, we save the user and send a notification e-mail.</p>



<h2 class="wp-block-heading" id="h-positive-amp-negative-scenario">Positive &amp; Negative Scenario</h2>



<p>Following, let&#8217;s do something different compared to other content about MockK. Let&#8217;s start by taking a look at the final result, and then we will see how we can get there.</p>



<p>So, firstly, let&#8217;s add the negative scenario:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class AwesomeMockkTest {

    private val userRepository: UserRepository = mockk()
    private val emailService = mockk&lt;EmailService>()

    private val service = UserService(userRepository, emailService)

    @Test
    fun `should throw IllegalArgumentException when user with given e-mail already exists`() {
        val email = "contact@codersee.com"
        val password = "pwd"

        val foundUser = User(UUID.randomUUID(), email, password)
        every { userRepository.findUserByEmail(email) } returns foundUser

        assertThrows&lt;IllegalArgumentException> {
            service.createUser(email, password)
        }

        verifyAll { userRepository.findUserByEmail(email) }
    }
}</pre>



<p>As we can see, we start all by defining dependencies for <code>UserService</code> as MockK mocks, and then we simply inject them through the constructor.</p>



<p>After that, we add our JUnit 5 test that asserts if the <code>createUser</code> function has thrown an exception, nothing unusual. The &#8220;unusual&#8221; part here is the <em>every</em> and <em>verifyAll</em> &#8211; those two blocks come from MockK, and we will get back to them in a moment.</p>



<p>With that done, let&#8217;s add one more test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should return UUID when user with given e-mail successfully created`() {
    val email = "contact@codersee.com"
    val password = "pwd"
    val createdUserUUID = UUID.randomUUID()

    every { userRepository.findUserByEmail(email) } returns null
    every { userRepository.saveUser(email, password) } returns createdUserUUID
    every {
        emailService.sendEmail(
            to = email,
            subject = "Welcome to Codersee!",
            body = "Welcome user: $createdUserUUID."
        )
    } just runs

    val result = service.createUser(email, password)

    assertEquals(createdUserUUID, result)

    verifyAll {
        userRepository.findUserByEmail(email)
        userRepository.saveUser(email, password)
        emailService.sendEmail(
            to = email,
            subject = "Welcome to Codersee!",
            body = "Welcome user: $createdUserUUID."
        )
    }
}</pre>



<p>This time, we test the positive scenario, in which the user was not found by the <code>e-mail</code> and was created successfully.</p>



<h2 class="wp-block-heading">Defining MockK Mocks</h2>



<p>With all of that done, let&#8217;s start breaking down things here.</p>



<p>Let&#8217;s take a look at what we did first:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private val userRepository: UserRepository = mockk()
private val emailService = mockk&lt;EmailService>()

private val service = UserService(userRepository, emailService)</pre>



<p>So, one of the approaches to define objects as <strong>mocks</strong> with MockK is by using the <code>mockk</code> function. </p>



<p>It is a generic function. So that&#8217;s why I presented both ways to invoke it. But please treat that as an example. In real life, I suggest you stick to either <code>mockk()</code> or <code>mockk&lt;EmailService&gt;()</code> for a cleaner code.</p>



<p>Alternatively, we can achieve exactly the same with MockK annotations:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@ExtendWith(MockKExtension::class)
class AwesomeMockkTest {

  @MockK
  lateinit var userRepository: UserRepository

  @MockK
  lateinit var emailService: EmailService

  @InjectMockKs
  lateinit var service: UserService

}</pre>



<p>The preferred approach is totally up to you. The important thing to mention is that the <code>@ExtendWith(MockKExtension::class)</code> comes from <strong>JUnit 5</strong>.</p>



<p>And for the <strong>JUnit 4</strong>, we would implement a rule:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class AwesomeMockkTest {
  @get:Rule
  val mockkRule = MockKRule(this)

  @MockK
  lateinit var userRepository: UserRepository

  @MockK
  lateinit var emailService: EmailService

  @InjectMockKs
  lateinit var service: UserService

}</pre>



<h2 class="wp-block-heading">Missing Stubbing</h2>



<p>At this point, we know that we don&#8217;t use real objects, but mocks.</p>



<p>Let&#8217;s try to run our test without defining any behavior:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Test
fun `should throw IllegalArgumentException when user with given e-mail already exists`() {
    val email = "contact@codersee.com"
    val password = "pwd"

    assertThrows&lt;IllegalArgumentException> {
        service.createUser(email, password)
    }

    verifyAll { userRepository.findUserByEmail(email) }
}</pre>



<p>In the console log, we should see the following:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Unexpected exception type thrown, expected: &lt;java.lang.IllegalArgumentException&gt; but was: &lt;io.mockk.MockKException&gt;</p>



<p>Expected :class java.lang.IllegalArgumentException</p>



<p>Actual :class io.mockk.MockKException</p>
</blockquote>



<p>Well, the issue is that when we do not specify a stubbing for a function that was invoked, MockK <strong>throws an exception</strong>.</p>



<p>But our test logic looks already for exception, so that&#8217;s why we got a message that this is simply an unexpected one.</p>



<p>Without the <code>assertThrows</code> , the message would be more obvious:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>no answer found for UserRepository(#1).findUserByEmail(contact@codersee.com) among the configured answers: (UserRepository(#1).saveUser(eq(contact@codersee.com), eq(pwd))))</p>



<p>io.mockk.MockKException: no answer found for UserRepository(#1).findUserByEmail(contact@codersee.com) among the configured answers: (UserRepository(#1).saveUser(eq(contact@codersee.com), eq(pwd))))</p>
</blockquote>



<p>So, <strong>lesson one</strong>: whenever we see a similar message, it means that our mock function was invoked, but we haven&#8217;t defined any stubbing.</p>



<h2 class="wp-block-heading" id="h-stubbing-in-mockk">Stubbing in MockK</h2>



<p>And we already saw how we can define a stubbing, but let&#8217;s take a look once again:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val foundUser = User(UUID.randomUUID(), email, password)
every { userRepository.findUserByEmail(email) } returns foundUser</pre>



<p>We can read the above function as &#8220;return <code>foundUser</code> every time the <code>findUserByEmail</code> function is invoked with this, specific email value&#8221;.</p>



<p>When we run the test now, everything is working fine. Because in our logic, if the <code>findUserByEmail</code> returns a not null value, an exception is thrown. So, no more functions are invoked. In other words, <strong>no more interactions with our mock</strong> object😉 Also, our email value matches.</p>



<p>And most of the time, this is how I would suggest defining stubbing. This way, we also make sure that the exact value of <code>email</code> is passed.</p>



<p>When it comes to the answer part, <code>returns foundUser</code>, we can also use alternatives, like:</p>



<ul class="wp-block-list">
<li><code>answers { code }</code> &#8211; to define a block of code to run (and/or return a value)</li>



<li><code>throws ex</code> &#8211; to throw exception</li>



<li>and many, many more (I will put a link to the docs at the end of this article)</li>
</ul>



<h2 class="wp-block-heading">MockK Matchers</h2>



<p>The above stubbing expects that the <code>email</code> value will be equal to what we define.</p>



<p>Technically, it is the equivalent of using the <code>eq</code> function:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""> every { userRepository.findUserByEmail(eq(email)) } returns foundUser</pre>



<p>And <code>eq</code> uses the <code>deepEquals</code> function to compare the values.</p>



<p>But sometimes, we do not want to, or we cannot define the exact value to match.</p>



<p>Let&#8217;s imagine that some function is invoked 20 times with various values. Technically, we could define all 20 matches.</p>



<p>But instead, we use one of the many matchers available in MockK, like <code>any</code> :</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""> every { userRepository.findUserByEmail(any()) } returns foundUser</pre>



<p>And whereas <code>eq</code> is the most concrete one, <code>any</code> is the most generic one. The <code>foundUser</code> is returned if <code>findUserByEmail</code> is invoked with anything.</p>



<p>And MockK comes with plenty of other matchers, like:</p>



<ul class="wp-block-list">
<li><code>any(Class)</code> &#8211; to match only if an instance of a given Class is passed</li>



<li><code>isNull</code> / <code>isNull(inverse=true)</code> &#8211; for null check</li>



<li><code>cmpEq(value)</code> , <code>more(value)</code> , <code>less(value)</code> &#8211; for the <code>compareTo</code> comparisons</li>



<li>and many more that you can find in the documentation</li>
</ul>



<p>For example, let&#8217;s take a look at the <code>match</code> example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">every {
  userRepository.findUserByEmail(
    match { it.contains("@") }
  )
} returns foundUser</pre>



<p>As we can see, this way the <code>foundUser</code> will be returned only if the passed value contains <code>@</code> sign.</p>



<h2 class="wp-block-heading">Unit Functions</h2>



<p>At this point, we know how to deal with matchers and the <code>returns</code> .</p>



<p>But what if the function does not return anything? We saw that previously, so let&#8217;s take a look once again:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">every { emailService.sendEmail(any(), any(), any()) } just runs</pre>



<p>Matchers are irrelevant right now, so I replaced them with <code>any()</code> .</p>



<p>The important thing here is that <code>just runs</code> is one of the approaches.</p>



<p>Alternatively, we can achieve the same:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">every { emailService.sendEmail(any(), any(), any()) } returns Unit
every { emailService.sendEmail(any(), any(), any()) } answers { }
justRun { emailService.sendEmail(any(), any(), any()) } </pre>



<p>The choice here is totally up to you.</p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>And that&#8217;s all for our first lesson dedicated to MockK and Kotlin. </p>



<p>As I mentioned above, <a href="https://mockk.io/" target="_blank" rel="noreferrer noopener">right here</a> you can find the MockK documentation. And although I strongly encourage you to visit it, I also would suggest doing it after my series- when we cover the most important concepts:</p>



<ul class="wp-block-list">
<li>Getting Started with MockK in Kotlin [1/5]</li>



<li><a href="https://blog.codersee.com/verification-mockk/">Verification in MockK [2/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-objects-top-level-extension-functions/">MockK: Objects, Top-Level, and Extension Functions [3/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-spy-relaxed-mock-partial-mocking/">MockK: Spies, Relaxed Mocks, and Partial Mocking [4/5]</a></li>



<li><a href="https://blog.codersee.com/mockk-coroutines/">MockK with Coroutines [5/5]</a></li>
</ul>



<p></p>
<p>The post <a href="https://blog.codersee.com/getting-started-with-mockk-kotlin/">Getting Started with MockK in Kotlin [1/5]</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/getting-started-with-mockk-kotlin/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Reactive Programming in Kotlin: A Step-by-Step Guide</title>
		<link>https://blog.codersee.com/reactive-programming-in-kotlin-a-step-by-step-guide/</link>
					<comments>https://blog.codersee.com/reactive-programming-in-kotlin-a-step-by-step-guide/#respond</comments>
		
		<dc:creator><![CDATA[Peter Lantukh]]></dc:creator>
		<pubDate>Thu, 15 Feb 2024 05:00:00 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Coroutines]]></category>
		<category><![CDATA[Reactive Programming]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=9508665</guid>

					<description><![CDATA[<p>This article provides a general overview of Reactive Programming and tools available in Kotlin in terms of Reactive Programming.</p>
<p>The post <a href="https://blog.codersee.com/reactive-programming-in-kotlin-a-step-by-step-guide/">Reactive Programming in Kotlin: A Step-by-Step Guide</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In this article, we are going to tackle <strong>Reactive Programming in Kotlin</strong>. We will start with what exactly <strong>Reactive Programming</strong> is, how we could use it to our advantage, and what techniques we can use in <strong>Kotlin</strong>. I am going to explain everything in simple terms to make this article <strong>beginner-friendly</strong> (considering you know the basics of Kotlin, of course).</p>



<p>In some <strong>future articles</strong>, we will put that knowledge into action on the <strong>example of the Ktor project</strong>, emphasizing the Reactive approach. So don&#8217;t forget to follow me on <a href="https://www.linkedin.com/in/peter-lantukh/" target="_blank" rel="noreferrer noopener">LinkedIn</a> to not miss out 🙂  </p>



<h2 class="wp-block-heading" id="h-reactive-programming">Reactive Programming</h2>



<p>If you try to search for what <strong>Reactive Programming</strong> is, you will sooner or later find The <strong><a href="https://www.reactivemanifesto.org/" target="_blank" rel="noreferrer noopener">Reactive Manifesto,</a></strong> which is cited by almost everyone. </p>



<p>And in most articles, there will be something like the following diagram:</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="501" height="281" src="http://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach-1.png" alt="Image presents reactive programming diagram about manifesto: responsive, elastic, resilient, message driven. " class="wp-image-9508673" srcset="https://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach-1.png 501w, https://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach-1-300x168.png 300w" sizes="auto, (max-width: 501px) 100vw, 501px" /></figure>



<p>For the beginner, all of these definitions and explanations are <strong>vague and unclear</strong>. It is absolutely possible to learn it and speak about it, for example, in an interview with zero understanding whatsoever. Instead, <strong>let&#8217;s connect it to concepts that are present in software development</strong>, and don&#8217;t worry if you are not familiar with them. </p>



<p>Let&#8217;s take a look at another diagram that represents the concepts:</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="401" height="181" src="http://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach2-1.png" alt="Image presents diagram with observer and interator pattern." class="wp-image-9508674" srcset="https://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach2-1.png 401w, https://blog.codersee.com/wp-content/uploads/2024/02/ReactiveApproach2-1-300x135.png 300w" sizes="auto, (max-width: 401px) 100vw, 401px" /></figure>



<p>The key concepts in the <strong>Observer Pattern</strong> are &#8220;<strong>subjects</strong>&#8221; and &#8220;<strong>observers</strong>&#8220;. When a subject&#8217;s <strong>state changes</strong>, it <strong>notifies</strong> all its observers, allowing them to react accordingly.</p>



<p>The <strong>Iterator Pattern</strong> introduces a way to access elements of some object, most likely a collection, sequentially without exposing its internal implementation.</p>



<p>And as a cherry on top, Reactive Programming is tight with <strong>Functional Programming</strong> so, in essence, let&#8217;s define what Reactive Programming is in these terms. Reactive Programming leverages the <strong>Observer&#8217;s one-to-many notification</strong> and the <strong>Iterator&#8217;s sequential access</strong>, but extends them to handle continuous data flows and <strong>asynchronous interactions</strong> without defining &#8220;what&#8221; to do with data but &#8220;how&#8221; to iterate.</p>



<h2 class="wp-block-heading" id="h-streams">Streams</h2>



<p>All mentioned before leads us to another core concept: <strong>Streams</strong>. If you are familiar with the Flows, it is basically them, if not we&#8217;ll cover them later anyway. So, a Stream is a <strong>sequence of data objects</strong> that can be consumed and processed asynchronously. What is more, you can also merge, filter, combine, and transform them to handle data successfully.</p>



<p>Now let&#8217;s check what Kotlin can offer in terms of the Reactive Approach. We will start with asynchronicity, and the best solution for this is Coroutines and especially Flows. But before that, let&#8217;s discuss types of streams.</p>



<h2 class="wp-block-heading" id="h-cold-and-hot-streams">&#8220;Cold&#8221; and &#8220;Hot&#8221; Streams</h2>



<p>In terms of emitting data, we have <strong>two types of streams</strong>. On the one hand, &#8220;<strong>cold</strong>&#8221; streams are streams that can only emit data when there is someone who could consume it, in other words, if there is any <strong>observer attached</strong>. This basically means that no data would be missed and the whole chain of the items consumed. </p>



<p>On the other hand, we have &#8220;<strong>hot</strong>&#8221; streams. They are <strong>not dependent on any observable</strong> attached and start emitting items as soon as they are created. And here is the key difference, you could &#8220;<strong>miss</strong>&#8221; values using &#8220;hot&#8221; streams if they are not handled carefully. </p>



<h2 class="wp-block-heading" id="h-kotlin-coroutines">Kotlin Coroutines </h2>



<p>Quick dive into Coroutines basics, and then we will, Coroutines allow us to create an <strong>asynchronous code execution</strong> just like threads, but they are <strong>not bound to any particular thread</strong> and without callbacks.</p>



<p>Now for the real part, the Reactive Programming Coroutines library can offer 3 options: </p>



<ul class="wp-block-list">
<li>Channels</li>



<li>StateFlow</li>



<li>SharedFlow</li>
</ul>



<p>Both StateFlow and SharedFlow are evolutions of the <strong>Flow</strong> which is generally a Stream I&#8217;ve mentioned before. Flow represents a <strong>sequence of values that can be computed asynchronously</strong>. But firstly, let&#8217;s start from Channels.</p>



<h2 class="wp-block-heading" id="h-channels">Channels</h2>



<p>The first notable object is <strong>Chanel</strong>. As documentation states, Chanel provides communication between coroutines. But in terms of our topic, Chanel is a &#8220;hot&#8221; Stream in which <strong>each individual value could consume only one observer</strong>. </p>



<p>Nevertheless, it can have more the one observer, but the values would be delivered to the first awaited. If there are many observers that wait for the value to be delivered, some collectors will get suspended. Now let&#8217;s check a simple code example: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

suspend fun fetchStockPrice(): Double {
    delay(1000) // Simulate API call delay
    return Math.random() * 100
}

fun main() = runBlocking {
    // Create a Chanel to hold stock prices
    val stockPrices = Channel&lt;Double>()

    // Launch a coroutine to fetch prices every second
    launch {
        while (isActive) {
            val price = fetchStockPrice()
            stockPrices.send(price)
            delay(1000)
        }
    }

    // Launch a coroutine to consume and display prices
    launch {
        for (price in stockPrices) {
            println("Current Stock Price: $$price")
        }
    }

    delay(Long.MAX_VALUE)
}</pre>



<p>This example simulates a stock price ticker application that fetches prices from an API in real time and displays them to the user. </p>



<p>We used Channel to handle the asynchronous data flow and transfer data from one Coroutine to another!</p>



<h2 class="wp-block-heading" id="h-sharedflow">SharedFlow</h2>



<p>The SharedFlow is a Stream in all of its glory. </p>



<p>It is a <strong>hot</strong> stream, that can have <strong>multiple numbers of observers.</strong> We can check it out with the following code example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

data class Item(val name: String, val price: Double)

fun main() = runBlocking {
    // SharedFlow to hold the cart items
    val cartItems = MutableSharedFlow&lt;List&lt;Item>>()

    // Launch a coroutine to print the cart on SharedFlow
    launch {
        cartItems.collect { items ->
            println("Cart Updated: $items")
        }
    }

    // Launch another coroutine to trigger order confirmation when the cart is full
    launch {
        cartItems.filter { it.size >= 3 } // Filter for 3 or more items
            .onEach { println("Order Confirmation triggered!") }
            .launchIn(this)
    }

    // Launch a coroutine to simulate adding items to the cart
    launch {
        var updatedItems = listOf(Item("Apple", 1.50))
        cartItems.emit(updatedItems)
        delay(1000)
        updatedItems = updatedItems + Item("Milk", 2.00)
        cartItems.emit(updatedItems)
        delay(1000)
        updatedItems = updatedItems + Item("Bread", 3.00)
        cartItems.emit(updatedItems)
    }

    delay(Long.MAX_VALUE)
}</pre>



<p>In the example above, we created a shopping cart application where multiple components need to react to changes in the cart items. </p>



<p>SharedFlow provides a centralized way to share updates efficiently. And we can witness multiple observers at the same time.</p>



<h2 class="wp-block-heading" id="h-stateflow">StateFlow</h2>



<p>The StateFlow is similar to SharedFlow. However, it is a somewhat <strong>cold</strong> stream because it <strong>requires some initial value</strong> on creation, and it <strong>always holds a value</strong>. </p>



<p>This basically means that it always has a value to observe. Here&#8217;s a good example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

enum class PlayerState {
    Playing,
    Paused,
    Stopped
}

fun main() = runBlocking {
    // StateFlow to hold the current player state
    val playerState = MutableStateFlow(PlayerState.Stopped)

    // Launch a coroutine to print state based on StateFlow
    launch {
        playerState.collect { state ->
            println("Player State: $state")
        }
    }

    // Launch a coroutine to simulate user actions
    launch {
        // Play/pause/stop actions update the state
        playerState.emit(PlayerState.Playing)
        delay(2000)
        playerState.emit(PlayerState.Paused)
        delay(1000)
        playerState.emit(PlayerState.Stopped)
    }

    delay(Long.MAX_VALUE)
}</pre>



<p>For this example, we use a music player application where the current playing state needs to be tracked. StateFlow provides a single source of truth for this state, with an initial value.</p>



<h2 class="wp-block-heading" id="h-other-reactive-options-available">Other Reactive options available</h2>



<p>The most popular alternatives are <strong>ReactiveX libraries</strong>. The main competitor is RxJava for Java basically and it&#8217;s widely used especially in <strong>Android Development</strong>. Unfortunately, <strong>RxKotlin</strong> has almost zero popularity these days due to its extensive RxJava presence. </p>



<p>RxJava provides extensive tools for Reactive programming, but due to its limited integration with <strong>Kotlin Coroutines</strong>, I recommend using Coroutines but keep in mind that this powerful tool is also available.</p>



<p>There are also lots of libraries tightly connected to <strong>Spring Boot</strong>. There are <strong>Spring WebFlux, and Project Reactor.</strong> They are provided tools in applications for building reactive systems in <strong>JVM Backend Development,</strong> but not that popular in Kotlin. </p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>And that’s all for this article about Reactive Programming in Kotlin with Coroutines and Flows.</p>



<p>In the upcoming articles, we will get back to this topic and learn how to apply this knowledge with Ktor, so don’t forget to join the free newsletter to not miss it!</p>



<p>Lastly, if you would like to learn more about Flows, then you can find lots of useful information on the <a href="https://kotlinlang.org/docs/flow.html">official documentation</a> of Kotlin.</p>
<p>The post <a href="https://blog.codersee.com/reactive-programming-in-kotlin-a-step-by-step-guide/">Reactive Programming in Kotlin: A Step-by-Step Guide</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/reactive-programming-in-kotlin-a-step-by-step-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>kotlinx.serialization in Kotlin- All You Need To Know</title>
		<link>https://blog.codersee.com/kotlinx-serialization-in-kotlin-all-you-need-to-know/</link>
					<comments>https://blog.codersee.com/kotlinx-serialization-in-kotlin-all-you-need-to-know/#respond</comments>
		
		<dc:creator><![CDATA[Peter Lantukh]]></dc:creator>
		<pubDate>Tue, 12 Dec 2023 06:00:00 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Core Kotlin]]></category>
		<category><![CDATA[kotlinx]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=9008417</guid>

					<description><![CDATA[<p>In this article, we will cover the most important scenarios of kotlinx.serialization in Kotlin and how to use it to your advantage.</p>
<p>The post <a href="https://blog.codersee.com/kotlinx-serialization-in-kotlin-all-you-need-to-know/">kotlinx.serialization in Kotlin- All You Need To Know</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you are working with Kotlin, then it is a matter of time before you will face a need to <strong>serialize </strong>and <strong>deserialize </strong>your data.&nbsp;In this topic, I am going to cover the most important scenarios of <strong>kotlinx.serialization in Kotlin</strong> and how to use it to your advantage in your projects.</p>



<p>If you haven&#8217;t heard about it, then Kotlin Serialization is a <strong>cross-platform</strong> and multi-format framework built for this specific needs. It can be used with practically any Kotlin-based project, such as Android applications, Ktor applications, and Multiplatform (Common, JS, Native).&nbsp;</p>



<h2 class="wp-block-heading" id="h-setting-up">Setting Up</h2>



<p>To set up kotlinx.serialization in our project, we must add the following lines in your <strong>build.gradle.kts</strong>. </p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plugins {

    kotlin("jvm") version "1.9.20" // or kotlin("multiplatform")

    kotlin("plugin.serialization") version "1.9.20"

}</pre>



<p>This will add the plugin. </p>



<p>Following, let&#8217;s add the implementation of the library itself:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">repositories {

    mavenCentral()

}

dependencies {

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1")

}</pre>



<p>Now we&#8217;re ready to go!</p>



<h2 class="wp-block-heading" id="h-basic-serialization">Basic Serialization</h2>



<h3 class="wp-block-heading" id="h-simple-objects">Simple Objects</h3>



<p>You may not used this library yourself but you might have seen a <strong>@Serializable</strong> annotation before. </p>



<p>This is practically all we&#8217;re going to need to set up a serialization for a particular class, like this:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  val userName: String
)</pre>



<p>Now, to manually serialize it, we only need to use a <strong>Json.encodeToString()</strong>. </p>



<p>For example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = User(userId = 1, userName = "Alice")
println(
  Json.encodeToString(data)
)</pre>



<p>The output would be the following:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1,"userName":"Alice"}</pre>



<p>On the other hand, to deserialize something, we&#8217;ll use <strong>Json.decodeFromString()</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = """  
  {
    "userId": 1,
    "userName":"Alice"
  }
"""  

println(
  Json.decodeFromString(
    User.serializer(), 
    data
  )
)</pre>



<p>The output:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">User(userId=1, userName=Alice)</pre>



<p>kotlinx.serialization has also some useful functions to work with <strong>InputStream</strong> rather than with <strong>String</strong>. However, they are experimental at the moment and require using <strong>@OptIn(ExperimentalSerializationApi::class)</strong>.  </p>



<p>What am I talking about here? The <strong>Json.encodeFromStream()</strong> and <strong>Json.decodeFromStream()</strong>, which come in handy when we are dealing with Files.</p>



<p>Let&#8217;s take a look at how we can get data from the file without reading it and converting it to String. It saves lots of computation time, particularly on a big scale:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@OptIn(ExperimentalSerializationApi::class)
fun deserializeFile(file: File): User {
  return Json.decodeFromStream(
    User.serializer(),
    file.inputStream()
  )
}</pre>



<p>Similarly, to encode it to a file we will use the <strong>encodeToStream</strong>:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@OptIn(ExperimentalSerializationApi::class)
fun serializeFile(user: User, file: File) {
  Json.encodeToStream(
    User.serializer(),
    user,
    file.outputStream()
  )
}</pre>



<h3 class="wp-block-heading" id="h-nested-referenced-objects">Nested(Referenced) Objects</h3>



<p>As the next step, let&#8217;s talk about <strong>nested serialization</strong>. </p>



<p>Highly likely, that some of your classes have a property that is another class. </p>



<p>In such a case, there is practically no difference from the previous section, just all of our classes have to have a <strong>@Serializable</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class Profile(
  val id: Int,
  val user: User
)

@Serializable
data class User(
  val userId: Int,
  val userName: String
)</pre>



<p>Let&#8217;s check it out like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val originalProfile = Profile(
  id = 123, 
  user = User(userId = 1, userName = "Alice")
)
  
println( 
  Json.encodeToString(
    Profile.serializer(), 
    originalProfile
  )
)  

val jsonString = """  
  {
    "id":123,
    "user": {
      "userId": 1,
      "userName":"Alice"
    }
  }
"""  

val deserializedProfile = Json.decodeFromString(
  Profile.serializer(), 
  jsonString
)
  
println(deserializedProfile)</pre>



<p>The output:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"id":123,"user":{"userId":1,"userName":"Alice"}}
Profile(id=123, user=User(userId=1, userName=Alice))</pre>



<h3 class="wp-block-heading" id="h-lists">Lists</h3>



<p>To serialize the whole List, we can use the <strong>ListSerializer</strong> constructor to create a serializer for any type of list, as long as <strong>we provide a serializer for the element type</strong>. </p>



<p>For example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val originalUsers = listOf(
  User(userId = 1, userName = "Alice"),
  User(userId = 2, userName = "Bob")
)  

println(
  Json.encodeToString(
    ListSerializer(User.serializer()), 
    originalUsers
  )
)  

val jsonString = """ 
  [
    {"userId":1,"userName":"Alice"},
    {"userId":2,"userName":"Bob"}
  ] 
"""  

val deserializedUsers = Json.decodeFromString(
  ListSerializer(User.serializer()), 
  jsonString
)  

println(deserializedUsers)</pre>



<p>That code will give us:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{"userId":1,"userName":"Alice"},{"userId":2,"userName":"Bob"}]
[User(userId=1, userName=Alice), User(userId=2, userName=Bob)]</pre>



<h3 class="wp-block-heading" id="h-generics">Generics</h3>



<p>Basically, generics serialization works the same as nested objects. </p>



<p>The kotlinx.serialization has type-polymorphic behavior, which means that JSON relies on the actual type parameter. It will be compiled successfully if the actual generic type is a serializable class. </p>



<p>To check that, let&#8217;s modify our classes:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class Profile&lt;T>(
  val id: T,
  val user: Wrapper&lt;T>
)

@Serializable
data class Wrapper&lt;T>(val contents: T)</pre>



<p>Now we can check how it will work with different T for user fields:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val profile1 = Profile(
  1, 
  Wrapper(
    User(userId = 1, userName = "Alice")
  )
)  
val profile2 = Profile(
  2, 
  Wrapper(42)
)  
  
val jsonProfile1 = Json.encodeToString(profile1)  
val jsonProfile2 = Json.encodeToString(profile2)  
  
println(jsonProfile1)  
println(jsonProfile2)  
  
val jsonString1 = """ 
  {
    "id": 1,
    "user": {
      "contents": {
        "userId": 1,
        "userName": "Alice"
      }
    }
  } 
"""  
val jsonString2 = """ 
  {
    "id": 2,
    "user": {
      "contents": 42
    }
  } 
"""  
  
val deserializedProfile1 = Json.decodeFromString(
  Profile.serializer(
    User.serializer()
  ),
  jsonString1
)  
val deserializedProfile2 = Json.decodeFromString(
  Profile.serializer(
    Int.serializer()
  ), 
  jsonString2
)  
  
println(deserializedProfile1)  
println(deserializedProfile2)</pre>



<p>There will be the following output:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"id":1,"user":{"contents":{"userId":1,"userName":"Alice"}}}
{"id":2,"user":{"contents":42}}
Profile(id=1, user=Wrapper(contents=User(userId=1, userName=Alice)))
Profile(id=2, user=Wrapper(contents=42))</pre>



<h2 class="wp-block-heading" id="h-customizing-serialization-and-deserialization">Customizing serialization and deserialization</h2>



<p>In this paragraph, we are gonna talk about making your objects a little bit appealing with variable behavior to adjust our specific needs.</p>



<h3 class="wp-block-heading" id="h-custom-names">Custom names</h3>



<p>As you have noticed, the basic name of a field is taken by default. </p>



<p>To create a custom name, the only thing we need is a <strong>@SerialName</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  @SerialName("id") val userId: Int,
  @SerialName("login") val userName: String
)</pre>



<p>Now let&#8217;s use it as we used in the example at the beginning:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = User(userId = 1, userName = "Alice")
println(
  Json.encodeToString(data)
)</pre>



<p>We&#8217;ll get:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"id":1,"login":"Alice"}</pre>



<p>But we must be careful- this works both ways. </p>



<p>After the change, we must make sure that the incoming JSON contains the names that we mentioned in the <strong>@SerialName</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = """{"id":1,"login":"Alice"}"""         //correct
val data = """{"userId":1,"userName":"Alice"}"""  //wrong</pre>



<h3 class="wp-block-heading" id="h-default-values">Default values</h3>



<p>Now things get a little bit trickier. Default values are not encoded by default. </p>



<p>So, if we want them to, we need the <strong>@EncodeDefault</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  @EncodeDefault val userName: String = "user"
)</pre>



<p>This way, we could omit a userName and the serialization library will use the default value:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = User(userId = 1)
println(
  Json.encodeToString(data)
)</pre>



<p>Let&#8217;s see:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1,"userName":"user"}</pre>



<p>Excellent, works as expected!</p>



<p>But here is a different situation. What if we want to deserialize a JSON with some optional fields? </p>



<p>For it to compile properly, we must provide a default value for these fields:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  val userName: String = "user"
)</pre>



<p>Now we can deserialize an object like this:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = """
  {
    "userId": 1
  }
"""
  
println(
  Json.decodeFromString(
    User.serializer(),
    data
  )
)</pre>



<p>Output:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">User(userId=1, userName=user)</pre>



<p>On the other hand, if we want an optional field to be present in JSON, we may use a <strong>@Required</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  @Required val userName: String = "user"
)</pre>



<p>If we use this class with the code before, <strong>we will get an error</strong>, which can be useful in some scenarios:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p></p>
<cite>Exception in thread &#8220;main&#8221; kotlinx.serialization.MissingFieldException: Field &#8216;userName&#8217; is required for type with serial name &#8216;com.example.User&#8217;, but it was missing</cite></blockquote>



<h3 class="wp-block-heading" id="h-nulls">Nulls</h3>



<p>Kotlin&#8217;s language is known for its type safety. The kotlinx.serialization knows it as well. </p>



<p>We cannot decode a null value into a non-nullable property or we get an exception. For example, for this class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  val userName: String
)</pre>



<p>We cannot expect to serialize this object below:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val data = """
  {
    "userId": 1,
     "userName": null
  }
"""
  
println(
  Json.decodeFromString(
    User.serializer(),
    data
  )
)</pre>



<p>It will result in an error.</p>



<p>To avoid it, we should do this instead:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  val userName: String?
)</pre>



<p>This time, our result will be:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">User(userId=1, userName=null)</pre>



<p>As we can see, default values are not encoded by default. </p>



<p>So to get a missing property from JSON not as an optional but as a null value, we have to use <strong>@EncodeDefault</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class User(
  val userId: Int,
  @EncodeDefault val userName: String? = null
)</pre>



<p>That is what we&#8217;ll see for our class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1,"userName":null}</pre>



<p>However, if we forget the annotation, this is what we will get:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1}</pre>



<h2 class="wp-block-heading" id="h-advanced-serialization">Advanced Serialization</h2>



<p>This section is probably what you are looking for if you have a complex project. </p>



<p>These are the most sophisticated tricks of kotlinx.serialization, but the most useful, though. And now we are going to understand how they work.</p>



<p>From now on everything becomes more complex. So we have to establish ground rules and basic terms. </p>



<h3 class="wp-block-heading" id="h-what-exactly-is-a-polymorphism">What Exactly Is a Polymorphism?</h3>



<p>Polymorphism in Kotlin is the ability of an object or a function to have different forms or behaviors depending on the context. A polymorphic object can belong to different classes and respond to the same method call in different ways. </p>



<p>There are two types of polymorphism in Kotlin: <strong>compile-time</strong> and <strong>run-time</strong>:</p>



<ul class="wp-block-list">
<li><strong>Compile-time</strong> polymorphism, also known as static polymorphism, is achieved through function overloading. It allows the name of functions, i.e., the signature, to be the same but return type or parameter lists to be different.</li>



<li><strong>Run-time </strong>polymorphism, or <strong>dynamic </strong>polymorphism, is achieved through function overriding and inheritance. In the run-time polymorphism, the compiler resolves a call to overload methods at the runtime.</li>
</ul>



<p>But there is more. For serialization, we are going to talk about different approaches. To serialize an object, we should know what that object is in the first place and can its behavior can be changed. So there are 2 more types of polymorphism:</p>



<ul class="wp-block-list">
<li><strong>Closed</strong> polymorphism means that the behavior of an object is fixed and cannot be changed by subclasses or external factors.</li>



<li><strong>Open</strong> polymorphism means that the behavior of an object can be modified or extended by subclasses or external factors.<br>This is how the library sees polymorphism for the most part.</li>
</ul>



<h3 class="wp-block-heading" id="h-the-practice-part">The Practice Part</h3>



<p>First things first, let&#8217;s talk about <strong>closed </strong>polymorphism in kotlinx.serialization. </p>



<p>The first and the most obvious thing to do is to make all of our classes serializable:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
open class User(
  val userId: Int,
  val userName: String?
)

@Serializable
@SerialName("admin")
class Admin(
  val adminId: Int,
  val adminName: String?,
  val adminRole: String
) : User(adminId, adminName)</pre>



<p>Let&#8217;s check it out:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun serializeAdmin() {
  val admin: User = Admin(
    adminId = 1,
    adminName = "Alice",
    adminRole = "Boss"
  )

  println(
    Json.encodeToString(admin)
  )
}</pre>



<p>Everything works as expected, our Admin is indeed a user:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1,"userName":"Alice"}</pre>



<p>But what will happen if we try to serialize an Admin object:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun serializeAdmin() {
  val admin = Admin(
    adminId = 1,
    adminName = "Alice",
    adminRole = "Boss"
  )

  println(
    Json.encodeToString(admin)
  )
}</pre>



<p>Let&#8217;s find out:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"userId":1,"userName":"Alice","adminId":1,"adminName":"Alice","adminRole":"Boss"}</pre>



<p>So you have to keep that in mind. This may be a bit odd.<br>Following this, I want to cover <strong>sealed classes</strong> as well. Not because I&#8217;m a huge fan of it, which I am, but because of its natural behavior (we know all of its children at the runtime) that helps our process:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
sealed class User {
  abstract val userId: Int
  abstract val userName: String?
}

@Serializable
@SerialName("admin")
class Admin(
  override val userId: Int,
  override val userName: String?,
  val adminRole: String
) : User()</pre>



<p>We are going to check our first scenario:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun serializeAdmin() {
  val admin: User = Admin(
    userId = 1,
    userName = "Alice",
    adminRole = "Boss"
  )

  println(
    Json.encodeToString(admin)
  )
}</pre>



<p>As expected, now we know the type of our user beforehand:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"type":"admin","userId":1,"userName":"Alice","adminRole":"Boss"}</pre>



<p>For a <strong>closed</strong> polymorphism, things get different. Now we have to create a <strong>SerializersModule</strong> and provide explicit subclasses that are to be serialized.</p>



<p>Let&#8217;s create an additional class to show this in action:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
abstract class User {
  abstract val userId: Int
  abstract val userName: String?
}

@Serializable
@SerialName("admin")
class Admin(
  override val userId: Int,
  override val userName: String?,
  val adminRole: String
) : User()

@Serializable
@SerialName("guest")
class Guest(
  override val userId: Int,
  override val userName: String?,
  val guestEmail: String?
) : User()</pre>



<p>Now comes the module:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val module = SerializersModule {
  polymorphic(User::class) {
    subclass(Admin::class, Admin.serializer())
    subclass(Guest::class, Guest.serializer())
  }
}</pre>



<p>We&#8217;ve used a <strong>Json</strong> instance for our needs before. Now we have to create a specific instance with our module:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val format = Json { serializersModule = module }</pre>



<p>With that done, let&#8217;s check it:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun serializeAdmin() {
  val admin: User = Admin(
    userId = 1,
    userName = "Alice",
    adminRole = "Boss"
  )
  val guest: User = Guest(
    userId = 1,
    userName = "Alice",
    guestEmail = "guest@email.com"
  )

  println(format.encodeToString(admin))
  println(format.encodeToString(guest))
}</pre>



<p>And this time, we get the following results:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"type":"admin","userId":1,"userName":"Alice","adminRole":"Boss"}
{"type":"guest","userId":1,"userName":"Alice","guestEmail":"guest@email.com"}</pre>



<p>We can serialize classes as long as we provide corresponding subclasses. </p>



<p>Of course, there is a lot to cover, for example, multiple superclasses or interfaces. But let&#8217;s stop here, maybe I&#8217;ll cover it explicitly in the other article. (Let me know if you are interested in this 🙂 ) </p>



<h3 class="wp-block-heading" id="h-custom-serializers">Custom serializers</h3>



<p>For some classes, happens that the default serialization method does not fulfill our needs. Or we want to create one that reflects a unique class utilization approach. For this purpose, <strong>custom serializers</strong> are our best friends. The most common examples are Date and Color. I&#8217;m gonna focus on Date.</p>



<p>Basically, there are 3 main parts of our custom serializer. Let&#8217;s check how the serializer for Date might look like:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">object DateSerializer : KSerializer&lt;Date> {
  private val dateFormat = SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSSZ")

  override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)

  override fun serialize(encoder: Encoder, value: Date) {
    encoder.encodeString(dateFormat.format(value))
  }

  override fun deserialize(decoder: Decoder): Date {
    return dateFormat.parse(decoder.decodeString())
  }
}</pre>



<p>We can already see all the necessary parts.</p>



<ul class="wp-block-list">
<li>The <strong>serialize</strong> function is used to turn an object into a sequence of simple values. It takes an Encoder and a value as inputs. It calls the encodeXxx functions of the Encoder to make the sequence. There is a different encodeXxx function for each simple type.</li>



<li>The <strong>deserialize</strong> function is used to turn a sequence of simple values back into an object. It takes a Decoder as input and returns a value. It calls the decodeXxx functions of the Decoder to get the sequence. These functions match the encodeXxx functions of the Encoder.</li>



<li>The <strong>descriptor</strong> property is used to tell how the encodeXxx and decodeXxx functions work. This helps the format to know what methods to use. Some formats can also use it to make a schema for the data.</li>
</ul>



<p>For our purposes, we can simplify the class. If there is no particular need in the <strong>descriptor</strong>, we can use a <strong>@Serializer(forClass = …)</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializer(forClass = Date::class)
object DateSerializer : KSerializer&lt;Date> {
  private val dateFormat = SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSSZ")

  override fun serialize(encoder: Encoder, value: Date) {
    encoder.encodeString(dateFormat.format(value))
  }

  override fun deserialize(decoder: Decoder): Date {
    return dateFormat.parse(decoder.decodeString())
  }
}</pre>



<p>To implement our custom serializer we should use a <strong>@Serializable(with = …)</strong> annotation for the corresponding property:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class Event(
  val name: String,
  @Serializable(with = DateSerializer::class)
  val date: Date
)</pre>



<p>Let&#8217;s see that in action:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val event = Event("Birthday Party", Date())  

val json = Json.encodeToString(event)  

println(json)</pre>



<p>With the result:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"name":"Birthday Party","date":"2023-11-23 T 17:12:36.069+0300"}</pre>



<p>As we can see, it has successfully been serialized to the desired date format.</p>



<h3 class="wp-block-heading" id="h-contextual-serialization">Contextual serialization</h3>



<p>Sometimes we need to change how we write objects as JSON at run-time, not just at compile-time, as we spoke before. This is called contextual serialization. </p>



<p>We can use the <strong>@Contextual</strong> annotation on a class or a property to tell Kotlin to use the ContextualSerializer class. This class will choose the right serializer for the object based on the context. We are going to use the previous serializer:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">object DateAsStringSerializer : KSerializer&lt;Date> {
  private val dateFormat = SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSSZ")

  override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)

  override fun serialize(encoder: Encoder, value: Date) {
    encoder.encodeString(dateFormat.format(value))
  }

  override fun deserialize(decoder: Decoder): Date {
    return dateFormat.parse(decoder.decodeString())
  }
}</pre>



<p>And our class will be looking like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Serializable
data class Event(
  val name: String,
  @Contextual val date: Date
)</pre>



<p>Now we need to create a <strong>SerializersModule</strong> in which we need to specify a serializers should be used for our contextually-serializable classes. </p>



<p>We can simply wrap our serializer in <strong>contextual</strong> function inside the module:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private val module = SerializersModule {
  contextual&lt;Date>(DateAsStringSerializer)
}  </pre>



<p>Now we create a format out of Json with our module: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val format = Json { serializersModule = module }</pre>



<p>Using our format of <strong>Json</strong> earlier, we&#8217;ll get our run-time serialization:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val event = Event("Birthday Party", Date())  

val json = format.encodeToString(event)  

println(json)</pre>



<p>With an expected output:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{"name":"Birthday Party","date":"2023-11-23 T 23:20:03.421+0300"}</pre>



<p></p>



<h2 class="wp-block-heading" id="h-kotlinx-serialization-summary">kotlinx.serialization Summary</h2>



<p>And that&#8217;s all for this article about <strong>serialization in Kotlin with kotlinx.serialization</strong>.</p>



<p>In the upcoming articles, we will get back to this topic and learn how to apply this knowledge with Ktor, so don&#8217;t forget to join the <a href="https://codersee.com/newsletter/">free newsletter</a> to not miss it!</p>



<p>Lastly, if you would like to learn more about kotlinx, then you can find lots of useful information on the official documentation of <a href="https://github.com/Kotlin/kotlinx.serialization" target="_blank" rel="noreferrer noopener">kotlinx</a>.&nbsp;</p>
<p>The post <a href="https://blog.codersee.com/kotlinx-serialization-in-kotlin-all-you-need-to-know/">kotlinx.serialization in Kotlin- All You Need To Know</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/kotlinx-serialization-in-kotlin-all-you-need-to-know/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Scope Control With @DslMarker Annotation. Kotlin DSLs.</title>
		<link>https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/</link>
					<comments>https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 07 Nov 2023 13:35:19 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Annotations]]></category>
		<category><![CDATA[Core Kotlin]]></category>
		<category><![CDATA[Kotlin DSL]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=9008328</guid>

					<description><![CDATA[<p>This time, I will show you how to control scope with @DslMarker annotation when creating your DSLs in Kotlin.</p>
<p>The post <a href="https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/">Scope Control With @DslMarker Annotation. Kotlin DSLs.</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Hello and welcome to the next lesson! This time, I will show you how to <strong>control scope with @DslMarker</strong> annotation when creating your DSLs in Kotlin. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p></p>
<cite>Note: this article is based on my Complete <a href="https://codersee.com/the-complete-kotlin-course/">Kotlin Course</a> lesson, which I highly encourage you to check out if you are looking for a comprehensive Kotlin guide. </cite></blockquote>



<p>If this is your first meeting with DSLs, then I would recommend you to check out my other article, in which I explain and show how to <a href="https://blog.codersee.com/kotlin-type-safe-builders-make-your-custom-dsl/">implement Kotlin DSL</a> step-by-step.</p>



<h2 class="wp-block-heading" id="h-video-tutorial">Video Tutorial</h2>



<p>If you prefer <strong>video content</strong>, then check out my video:</p>



<div style="text-align: center; width: 90%; margin-left: 5%;">
<a href="https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FuItQGNnbUXo%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /></p></div>



<p>If you find this content useful,<strong> please leave a subscription&nbsp;</strong> 😉</p>



<h2 class="wp-block-heading" id="h-uncontrolled-scope">Uncontrolled Scope</h2>



<p>But before we dive into the solution with Kotlin @DslMarker, let&#8217;s understand what problem it solves first. </p>



<p>So as the first step, let&#8217;s prepare a simple DSL with <code>Board</code>, <code>Task</code>, <code>Author</code>, and <code>Comment</code> classes:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">enum class BoardColor {
  BLACK, WHITE, GREEN, BLUE
}

class Board {
  var title: String = ""
  var color: BoardColor = BoardColor.BLUE
  val tasks: MutableList&lt;Task> = mutableListOf()

  fun task(init: Task.() -> Unit) {
    val task = Task().apply(init)
    tasks.add(task)
  }
}

class Task {
  var title: String = ""
  var description: String = ""
  val comments: MutableList&lt;Comment> = mutableListOf()

  fun comment(init: Comment.() -> Unit) {
    val comment = Comment().apply(init)
    comments.add(comment)
  }
}

class Comment {
  var comment: String = ""
  var author: Author = Author()

  fun author(init: Author.() -> Unit) {
    val author = Author().apply(init)
    this.author = author
  }
}

class Author {
  var name: String = ""
}

fun board(init: Board.() -> Unit): Board =
  Board()
    .apply(init)</pre>



<p>With the following Kotlin DSL implementation, we would expect that we could introduce different Boards, with Tasks inside them, which would have some Comments written by Authors. </p>



<p>But let&#8217;s take a look at the following code: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun main() {
  val board = board {
    task {
      task {
        task {
          comment {
            task { }
            author {
              task { }
              comment {
                task { }
              }
            }
          }
        }
      }
    }
  }
}</pre>



<p>Will it compile? <strong>Unfortunately, yes</strong>.</p>



<p>We invoke a <em>task</em> within a <em>task</em>, within a <em>task</em>, and so on. Moreover, we can invoke the <em>task</em>, or <em>comment</em> functions inside the <em>author</em>.&nbsp;</p>



<p>And that&#8217;s because, <strong>by default, we can call the methods of every available receive</strong>r, which can lead to such situations.&nbsp;</p>



<h2 class="wp-block-heading" id="h-kotlin-dslmarker-to-the-rescue">Kotlin @DslMarker To The Rescue</h2>



<p>At this point, we already know what the issue is and what we will use to fix it. </p>



<p>But what exactly does the @DslMarker do in Kotlin? </p>



<p>Well, in practice, we use this annotation to introduce our new custom annotations. Then, we make use of them to mark classes and receivers, thus preventing receivers marked with the same annotation from being accessed inside one another.</p>



<p>This way, we won’t be able to access members of the outer receiver (like the&nbsp;<em>task&nbsp;</em>function, which is declared inside the&nbsp;<em>Board</em> class from the <em>Task</em> class instances).</p>



<p>Let&#8217;s consider the updated example: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@DslMarker
annotation class BoardDsl

enum class BoardColor {
  BLACK, WHITE, GREEN, BLUE
}

@BoardDsl
class Board {
  var title: String = ""
  var color: BoardColor = BoardColor.BLUE
  val tasks: MutableList&lt;Task> = mutableListOf()

  fun task(init: Task.() -> Unit) {
    val task = Task().apply(init)
    tasks.add(task)
  }
}

@BoardDsl
class Task {
  var title: String = ""
  var description: String = ""
  val comments: MutableList&lt;Comment> = mutableListOf()

  fun comment(init: Comment.() -> Unit) {
    val comment = Comment().apply(init)
    comments.add(comment)
  }
}

@BoardDsl
class Comment {
  var comment: String = ""
  var author: Author = Author()

  fun author(init: Author.() -> Unit) {
    val author = Author().apply(init)
    this.author = author
  }
}

@BoardDsl
class Author {
  var name: String = ""
}

fun board(init: Board.() -> Unit): Board =
  Board()
    .apply(init)

fun main() {
  val board = board {
    task {  // OK
      task {  // Does not compile
        task {  // Does not compile
          comment {  // OK
            task { }  // Does not compile
            author {  // OK
              task { }  // Does not compile
              comment {  // Does not compile
                task { }  // Does not compile
              }
            }
          }
        }
      }
    }
  }
}</pre>



<p>Firstly, we introduce the <code>@BoardDsl</code> annotation, which uses the <code>@DslMarker</code>. </p>



<p>Following, we must annotate every class in our hierarchy with our new annotation- this way, we make the Kotlin compiler &#8220;aware&#8221; of the hierarchy in our DSL. </p>



<p>Lastly, we can clearly see that the code <strong>will not compile</strong> whenever we try to nest the unwanted type inside another. </p>



<h2 class="wp-block-heading" id="h-scope-control-with-kotlin-dslmarker-summary">Scope Control With Kotlin @DslMarker Summary</h2>



<p>Basically, that&#8217;s all for this tutorial on <strong>how to control scope</strong> when implementing a <strong>Kotlin DSL</strong> using the <strong>@DslMarker </strong>summary.</p>



<p>If you enjoy such a short, practice-focused learning approach then do not forget to check out my course and let me know in the comments section. </p>



<p>If you&#8217;d like to learn a bit more about the annotation itself, then the <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-dsl-marker/" target="_blank" rel="noreferrer noopener">documentation</a> may be useful to you too. </p>
<p>The post <a href="https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/">Scope Control With @DslMarker Annotation. Kotlin DSLs.</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/scope-control-dslmarker-kotlin-dsl/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: blog.codersee.com @ 2026-02-21 10:41:02 by W3 Total Cache
-->