{"id":397,"date":"2025-03-04T17:55:01","date_gmt":"2025-03-04T17:55:01","guid":{"rendered":"https:\/\/imcodinggenius.com\/?p=397"},"modified":"2025-03-04T17:55:01","modified_gmt":"2025-03-04T17:55:01","slug":"getting-started-with-mockk-in-kotlin-1-5","status":"publish","type":"post","link":"https:\/\/imcodinggenius.com\/?p=397","title":{"rendered":"Getting Started with MockK in Kotlin [1\/5]"},"content":{"rendered":"<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>\n<p>Getting Started with MockK in Kotlin [1\/5]<\/p>\n<p><a href=\"https:\/\/codersee.com\/verification-mockk\/\">Verification in MockK [2\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-objects-top-level-extension-functions\/\">MockK: Objects, Top-Level, and Extension Functions [3\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-spy-relaxed-mock-partial-mocking\/\">MockK: Spies, Relaxed Mocks, and Partial Mocking [4\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-coroutines\/\">MockK with Coroutines [5\/5]<\/a><\/p>\n<p>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\u2019re gonna love it!  <\/p>\n<h2 class=\"wp-block-heading\">Why Do We Need Mocking?<\/h2>\n<p>Long story short, we need mocking to isolate the unit \/ the system under test.<\/p>\n<p>Sounds confusing? No worries.<\/p>\n<p>Let\u2019s take a look at the typical example of a function:<\/p>\n<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\u2019t matter.<\/p>\n<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>\n<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>\n<p>The important thing to remember is that mocking is not limited to functions. A, B, and C may as well represent services.<\/p>\n<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>\n<h2 class=\"wp-block-heading\">Mocking, Stubbing, Test Doubles<\/h2>\n<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>\n<p>Anyway, from the chronicler\u2019s duty, let me illustrate a few concepts:<\/p>\n<p><strong>stub <\/strong>is a fake object that returns hard-coded answers. Typically, we use it to return some value, but we don\u2019t care about additional info, like how many times it was invoked, etc.<\/p>\n<p><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.<\/p>\n<p><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<\/p>\n<p><strong>mocking<\/strong> means creating\/using a <em>mock<\/em><\/p>\n<p>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).<\/p>\n<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=\"noopener\">Martin Flower\u2019s article<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">MockK Imports<\/h2>\n<p>With all of that said, let\u2019s head to the practice part. <\/p>\n<p>Firstly, let\u2019s define the necessary imports for MockK.<\/p>\n<p>We will be working with a plain Kotlin \/ Gradle project with JUnit 5, so our build.gradle.kts dependencies should look as follows:<\/p>\n<p>dependencies {<br \/>\n    testImplementation(&#171;io.mockk:mockk:1.13.17&#187;)<br \/>\n    testImplementation(kotlin(&#171;test&#187;))<br \/>\n}<\/p>\n<p>tasks.test {<br \/>\n    useJUnitPlatform()<br \/>\n}<\/p>\n<p>The io.mockk:mockk 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>\n<h2 class=\"wp-block-heading\">Tested Code<\/h2>\n<p>Then, let\u2019s take a look at the code we are supposed to test:<\/p>\n<p>data class User(val id: UUID, val email: String, val passwordHash: String)<\/p>\n<p>class UserRepository {<br \/>\n    fun saveUser(email: String, passwordHash: String): UUID =<br \/>\n        UUID.fromString(&#171;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&#187;)<\/p>\n<p>    fun findUserByEmail(email: String): User? =<br \/>\n        User(<br \/>\n            id = UUID.fromString(&#171;bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb&#187;),<br \/>\n            email = &#171;found@codersee.com&#187;,<br \/>\n            passwordHash = &#171;foundPwd&#187;<br \/>\n        )<br \/>\n}<\/p>\n<p>class EmailService {<br \/>\n    fun sendEmail(to: String, subject: String, body: String) {<br \/>\n        println(&#171;Sending body $body to $to with subject $subject&#187;)<br \/>\n    }<br \/>\n}<\/p>\n<p>class UserService(<br \/>\n    private val userRepository: UserRepository,<br \/>\n    private val emailService: EmailService,<br \/>\n) {<\/p>\n<p>    fun createUser(email: String, password: String): UUID {<br \/>\n        userRepository.findUserByEmail(email)<br \/>\n            ?.let { throw IllegalArgumentException(&#171;User with email $email already exists&#187;) }<\/p>\n<p>        return userRepository.saveUser(email, password)<br \/>\n            .also { userId -&gt;<br \/>\n                emailService.sendEmail(<br \/>\n                    to = email,<br \/>\n                    subject = &#171;Welcome to Codersee!&#187;,<br \/>\n                    body = &#171;Welcome user: $userId.&#187;<br \/>\n                )<br \/>\n            }<br \/>\n    }<br \/>\n}<\/p>\n<p>As we can see, we have a simple example of a UserService with one function- createUser . The service and the function that we will focus on in our tests.<\/p>\n<p>And although UserRepository and EmailService look pretty weird, the createUser is more or less something we can find in our real-life code. We check if the given email is taken, and if that\u2019s the case, we throw an exception. Otherwise, we save the user and send a notification e-mail.<\/p>\n<h2 class=\"wp-block-heading\">Positive &amp; Negative Scenario<\/h2>\n<p>Following, let\u2019s do something different compared to other content about MockK. Let\u2019s start by taking a look at the final result, and then we will see how we can get there.<\/p>\n<p>So, firstly, let\u2019s add the negative scenario:<\/p>\n<p>class AwesomeMockkTest {<\/p>\n<p>    private val userRepository: UserRepository = mockk()<br \/>\n    private val emailService = mockk&lt;EmailService&gt;()<\/p>\n<p>    private val service = UserService(userRepository, emailService)<\/p>\n<p>    @Test<br \/>\n    fun `should throw IllegalArgumentException when user with given e-mail already exists`() {<br \/>\n        val email = &#171;contact@codersee.com&#187;<br \/>\n        val password = &#171;pwd&#187;<\/p>\n<p>        val foundUser = User(UUID.randomUUID(), email, password)<br \/>\n        every { userRepository.findUserByEmail(email) } returns foundUser<\/p>\n<p>        assertThrows&lt;IllegalArgumentException&gt; {<br \/>\n            service.createUser(email, password)<br \/>\n        }<\/p>\n<p>        verifyAll { userRepository.findUserByEmail(email) }<br \/>\n    }<br \/>\n}<\/p>\n<p>As we can see, we start all by defining dependencies for UserService as MockK mocks, and then we simply inject them through the constructor.<\/p>\n<p>After that, we add our JUnit 5 test that asserts if the createUser function has thrown an exception, nothing unusual. The \u201cunusual\u201d part here is the <em>every<\/em> and <em>verifyAll<\/em> \u2013 those two blocks come from MockK, and we will get back to them in a moment.<\/p>\n<p>With that done, let\u2019s add one more test:<\/p>\n<p>@Test<br \/>\nfun `should return UUID when user with given e-mail successfully created`() {<br \/>\n    val email = &#171;contact@codersee.com&#187;<br \/>\n    val password = &#171;pwd&#187;<br \/>\n    val createdUserUUID = UUID.randomUUID()<\/p>\n<p>    every { userRepository.findUserByEmail(email) } returns null<br \/>\n    every { userRepository.saveUser(email, password) } returns createdUserUUID<br \/>\n    every {<br \/>\n        emailService.sendEmail(<br \/>\n            to = email,<br \/>\n            subject = &#171;Welcome to Codersee!&#187;,<br \/>\n            body = &#171;Welcome user: $createdUserUUID.&#187;<br \/>\n        )<br \/>\n    } just runs<\/p>\n<p>    val result = service.createUser(email, password)<\/p>\n<p>    assertEquals(createdUserUUID, result)<\/p>\n<p>    verifyAll {<br \/>\n        userRepository.findUserByEmail(email)<br \/>\n        userRepository.saveUser(email, password)<br \/>\n        emailService.sendEmail(<br \/>\n            to = email,<br \/>\n            subject = &#171;Welcome to Codersee!&#187;,<br \/>\n            body = &#171;Welcome user: $createdUserUUID.&#187;<br \/>\n        )<br \/>\n    }<br \/>\n}<\/p>\n<p>This time, we test the positive scenario, in which the user was not found by the e-mail and was created successfully.<\/p>\n<h2 class=\"wp-block-heading\">Defining MockK Mocks<\/h2>\n<p>With all of that done, let\u2019s start breaking down things here.<\/p>\n<p>Let\u2019s take a look at what we did first:<\/p>\n<p>private val userRepository: UserRepository = mockk()<br \/>\nprivate val emailService = mockk&lt;EmailService&gt;()<\/p>\n<p>private val service = UserService(userRepository, emailService)<\/p>\n<p>So, one of the approaches to define objects as <strong>mocks<\/strong> with MockK is by using the mockk function. It is a generic function, so above, we can see both ways in which we can invoke it. It is just an example, and in real life I suggest you stick to either mockk() or mockk&lt;EmailService&gt;() for a cleaner code.<\/p>\n<p>Alternatively, we can achieve exactly the same with MockK annotations:<\/p>\n<p>@ExtendWith(MockKExtension::class)<br \/>\nclass AwesomeMockkTest {<\/p>\n<p>  @MockK<br \/>\n  lateinit var userRepository: UserRepository<\/p>\n<p>  @MockK<br \/>\n  lateinit var emailService: EmailService<\/p>\n<p>  @InjectMockKs<br \/>\n  lateinit var service: UserService<\/p>\n<p>}<\/p>\n<p>The preferred approach is totally up to you. The important thing to mention is that the @ExtendWith(MockKExtension::class) comes from <strong>JUnit 5<\/strong>.<\/p>\n<p>And for the <strong>JUnit 4<\/strong>, we would implement a rule:<\/p>\n<p>class AwesomeMockkTest {<br \/>\n  @get:Rule<br \/>\n  val mockkRule = MockKRule(this)<\/p>\n<p>  @MockK<br \/>\n  lateinit var userRepository: UserRepository<\/p>\n<p>  @MockK<br \/>\n  lateinit var emailService: EmailService<\/p>\n<p>  @InjectMockKs<br \/>\n  lateinit var service: UserService<\/p>\n<p>}<\/p>\n<h2 class=\"wp-block-heading\">Missing Stubbing<\/h2>\n<p>At this point, we know that we don\u2019t use real objects, but mocks.<\/p>\n<p>Let\u2019s try to run our test without defining any behavior:<\/p>\n<p>@Test<br \/>\nfun `should throw IllegalArgumentException when user with given e-mail already exists`() {<br \/>\n    val email = &#171;contact@codersee.com&#187;<br \/>\n    val password = &#171;pwd&#187;<\/p>\n<p>    assertThrows&lt;IllegalArgumentException&gt; {<br \/>\n        service.createUser(email, password)<br \/>\n    }<\/p>\n<p>    verifyAll { userRepository.findUserByEmail(email) }<br \/>\n}<\/p>\n<p>Well, we would get something like:<\/p>\n<p>Unexpected exception type thrown, expected: &lt;java.lang.IllegalArgumentException&gt; but was: &lt;io.mockk.MockKException&gt;<\/p>\n<p>Expected :class java.lang.IllegalArgumentException<\/p>\n<p>Actual :class io.mockk.MockKException<\/p>\n<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>\n<p>But our test logic looks already for exception, so that\u2019s why we got a message that this is simply an unexpected one.<\/p>\n<p>Without the assertThrows , the message would be more obvious:<\/p>\n<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>\n<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>\n<p>So, <strong>lesson one<\/strong>: whenever we see a similar message, it means that our mock function was invoked, but we haven\u2019t defined any stubbing.<\/p>\n<h2 class=\"wp-block-heading\">Stubbing in MockK<\/h2>\n<p>And we already saw how we can define a stubbing, but let\u2019s take a look once again:<\/p>\n<p>val foundUser = User(UUID.randomUUID(), email, password)<br \/>\nevery { userRepository.findUserByEmail(email) } returns foundUser<\/p>\n<p>We can read the above function as \u201creturn foundUser every time the findUserByEmail function is invoked with this, specific email value\u201d.<\/p>\n<p>When we run the test now, everything is working fine. Because in our logic, if the findUserByEmail 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>\n<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 email is passed.<\/p>\n<p>When it comes to the answer part, returns foundUser, we can also use alternatives, like:<\/p>\n<p>answers { code } \u2013 to define a block of code to run (and\/or return a value)<\/p>\n<p>throws ex \u2013 to throw exception<\/p>\n<p>and many, many more (I will put a link to the docs at the end of this article)<\/p>\n<h2 class=\"wp-block-heading\">MockK Matchers<\/h2>\n<p>The above stubbing expects that the email value will be equal to what we define.<\/p>\n<p>Technically, it is the equivalent of using the eq function:<\/p>\n<p> every { userRepository.findUserByEmail(eq(email)) } returns foundUser<\/p>\n<p>And eq uses the deepEquals function to compare the values.<\/p>\n<p>But sometimes, we do not want to, or we cannot define the exact value to match.<\/p>\n<p>Let\u2019s imagine that some function is invoked 20 times with various values. Technically, we could define all 20 matches.<\/p>\n<p>But instead, we use one of the many matchers available in MockK, like any :<\/p>\n<p> every { userRepository.findUserByEmail(any()) } returns foundUser<\/p>\n<p>And whereas eq is the most concrete one, any is the most generic one. The foundUser is returned if findUserByEmail is invoked with anything.<\/p>\n<p>And MockK comes with plenty of other matchers, like:<\/p>\n<p>any(Class) \u2013 to match only if an instance of a given Class is passed<\/p>\n<p>isNull \/ isNull(inverse=true) \u2013 for null check<\/p>\n<p>cmpEq(value) , more(value) , less(value) \u2013 for the compareTo comparisons<\/p>\n<p>and many more that you can find in the documentation<\/p>\n<p>For example, let\u2019s take a look at the match example:<\/p>\n<p>every {<br \/>\n  userRepository.findUserByEmail(<br \/>\n    match { it.contains(&#171;@&#187;) }<br \/>\n  )<br \/>\n} returns foundUser<\/p>\n<p>As we can see, this way the foundUser will be returned only if the passed value contains @ sign.<\/p>\n<h2 class=\"wp-block-heading\">Unit Functions<\/h2>\n<p>At this point, we know how to deal with matchers and the returns .<\/p>\n<p>But what if the function does not return anything? We saw that previously, so let\u2019s take a look once again:<\/p>\n<p>every { emailService.sendEmail(any(), any(), any()) } just runs<\/p>\n<p>Matchers are irrelevant right now, so I replaced them with any() .<\/p>\n<p>The important thing here is that just runs is one of the approaches.<\/p>\n<p>Alternatively, we can achieve the same:<\/p>\n<p>every { emailService.sendEmail(any(), any(), any()) } returns Unit<br \/>\nevery { emailService.sendEmail(any(), any(), any()) } answers { }<br \/>\njustRun { emailService.sendEmail(any(), any(), any()) } <\/p>\n<p>The choice here is totally up to you.<\/p>\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n<p>And that\u2019s all for our first lesson dedicated to MockK and Kotlin. <\/p>\n<p>As I mentioned above, <a href=\"https:\/\/mockk.io\/\" target=\"_blank\" rel=\"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>\n<p>Getting Started with MockK in Kotlin [1\/5]<\/p>\n<p><a href=\"https:\/\/codersee.com\/verification-mockk\/\">Verification in MockK [2\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-objects-top-level-extension-functions\/\">MockK: Objects, Top-Level, and Extension Functions [3\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-spy-relaxed-mock-partial-mocking\/\">MockK: Spies, Relaxed Mocks, and Partial Mocking [4\/5]<\/a><\/p>\n<p><a href=\"https:\/\/codersee.com\/mockk-coroutines\/\">MockK with Coroutines [5\/5]<\/a><\/p>\n<p>The post <a href=\"https:\/\/codersee.com\/getting-started-with-mockk-kotlin\/\">Getting Started with MockK in Kotlin [1\/5]<\/a> appeared first on <a href=\"https:\/\/codersee.com\/\">Codersee &#8212; Kotlin on the backend<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<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 MockK and Kotlin topics. Getting Started with MockK in Kotlin [1\/5] &#8230; <\/p>\n<div><a class=\"more-link bs-book_btn\" href=\"https:\/\/imcodinggenius.com\/?p=397\">Read More<\/a><\/div>\n","protected":false},"author":0,"featured_media":398,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-397","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts\/397"}],"collection":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=397"}],"version-history":[{"count":0,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/posts\/397\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=\/wp\/v2\/media\/398"}],"wp:attachment":[{"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imcodinggenius.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}