What if you could test your code without waiting for slow or unreliable services every time?
Why Mocking with MockK in Kotlin? - Purpose & Use Cases
Imagine you are testing a function that calls a database or a web service. Without mocking, you have to connect to the real database or wait for the real service every time you run your tests.
This manual approach is slow because real services can be slow or unreliable. It is also error-prone because the data might change or the service might be down, causing your tests to fail for reasons unrelated to your code.
Mocking with MockK lets you create fake versions of these services that behave exactly how you want during tests. This way, tests run fast, reliably, and only check your code's logic.
val result = realService.getData() assertEquals(expected, result)
every { mockService.getData() } returns expected
val result = mockService.getData()
assertEquals(expected, result)Mocking with MockK enables you to test your code in isolation, making tests faster, more reliable, and easier to write.
When building an app that fetches weather data from the internet, you can mock the weather service to return fixed data during tests, so your tests don't depend on internet connection or real weather changes.
Manual testing with real services is slow and unreliable.
MockK creates fake versions of dependencies for fast, stable tests.
This helps you focus on testing your own code's logic only.
Practice
Solution
Step 1: Understand mocking concept
Mocking means creating fake versions of objects to test code without using real dependencies.Step 2: Identify MockK's role
MockK is a Kotlin library that helps create these fake objects easily for testing purposes.Final Answer:
To create fake objects that simulate real ones for testing -> Option AQuick Check:
MockK = mocking tool for fake objects [OK]
- Confusing MockK with build or deployment tools
- Thinking MockK is for UI design
- Assuming MockK speeds up compilation
MyService using MockK?Solution
Step 1: Recall MockK syntax for mocking
MockK uses the functionmockk<ClassName>()to create mocks.Step 2: Check each option
val mock = mockk<MyService>() usesmockk<MyService>(), which is correct syntax. Others are invalid or not MockK functions.Final Answer:
val mock = mockk<MyService>() -> Option CQuick Check:
mockk<Class>() creates mock [OK]
- Using uppercase 'MockK' as a function
- Trying to use 'new' keyword in Kotlin
- Using non-existent functions like createMock
val mock = mockk<Calculator>()
every { mock.add(2, 3) } returns 10
println(mock.add(2, 3))
println(mock.add(1, 1))Solution
Step 1: Understand mocking behavior setup
The mock is told to return 10 whenadd(2, 3)is called.Step 2: Check calls and outputs
Callingmock.add(2, 3)returns 10 as set. Callingmock.add(1, 1)has no behavior defined, so MockK throws an exception by default.Final Answer:
10 Exception -> Option AQuick Check:
Defined call returns 10; undefined call throws exception [OK]
- Assuming undefined calls return 0 or null
- Thinking all calls return the same mocked value
- Ignoring that MockK throws exceptions on undefined calls
val mock = mockk<UserRepository>()
every { mock.getUser(any()) } returns User("Alice")
mock.getUser(1)
verify { mock.getUser(1) }Solution
Step 1: Analyze mocking and stubbing
The mock is created normally, andeverysets behavior for any argument usingany(), which is valid.Step 2: Check verification usage
After callingmock.getUser(1), theverifyblock correctly checks that the method was called with argument 1.Final Answer:
No error; code is correct -> Option BQuick Check:
any() matcher and verify block used correctly [OK]
- Thinking relaxed=true is always required
- Confusing verify usage with unnecessary calls
- Misusing any() matcher outside stubbing
PaymentProcessor so that calling process(amount) returns "Success" only when amount is greater than 100, otherwise throws an exception. Which MockK setup achieves this?Solution
Step 1: Understand conditional mocking with matchers
MockK supports argument matchers likegt()(greater than) andltEq()(less than or equal) for conditions.Step 2: Evaluate options for correct matcher usage
every { mock.process(gt(100)) } returns "Success" every { mock.process(ltEq(100)) } throws IllegalArgumentException() correctly usesgt(100)to return "Success" andltEq(100)to throw exception, matching the requirement precisely.Final Answer:
every { mock.process(gt(100)) } returns "Success" every { mock.process(ltEq(100)) } throws IllegalArgumentException() -> Option DQuick Check:
Use gt() and ltEq() for conditional mocking [OK]
- Using match { } lambda instead of built-in matchers
- Mocking only specific values, missing ranges
- Returning success for all inputs ignoring conditions
Ready to prove it?
Pass the test and this pattern moves unknown
