-
-
-
-
URL copied!
Mocking is a process that is used in unit testing when the unit being tested has external dependencies. For example, a code that initiates the downloading of an image (and finally conveys success-failure on the UI) will have a dependency on a NetworkModule. While unit testing this code, the NetworkModule should be mocked. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies. So in simple words, mocking is creating objects that simulate the behavior of real objects.
In Android, there are a lot of frameworks used for mocking in unit testing, such as PowerMock, Mockito, EasyMock, etc. MockK is definitely a better alternative to other mocking frameworks for Kotlin, the official development language for Android. Its main philosophy is first-class support for Kotlin features.
Mockito Framework and its Shortcomings
I started off with adding the Mockito dependency to my Kotlin project and wrote a simple unit test case.
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.13.0</version>
</dependency>
class DatabaseTest {
class GenerateRecord { fun generate(): String = "Random String" }
class Dao { fun insert(record: String) = println("""Inserting "$record"""") }
class Service(private val generator: GenerateRecord, private val dao: Dao) {
fun calculate() {
val record = generator.generate()
dao.insert(record)
}
}
val generator = Mockito.mock(GenerateRecord::class.java)
val dao = Mockito.mock(Dao::class.java)
val service = Service(generator, dao)
@Test
fun insertRecordTest() {
val mockedRecord = "mocked String"
Mockito.`when`(generator.generate()).thenReturn(mockedRecord)
service.calculate()
Mockito.verify(generator).generate()
Mockito.verify(dao).insert(mockedRecord)
Mockito.verifyNoMoreInteractions(generator, dao)
}
}
When you ran it, It gives you this nice error:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class GenerateRecord
Mockito cannot mock/spy because :
- final class
— anonymous classes
— primitive types
As all classes and methods are final by default in Kotlin, using Mockito appears to be a bit problematic due to how Mockito creates its mocks. You would have to explicitly make your classes inheritable using the open modifier. Another approach would be to add interfaces to everything.
Starting from Mockito version 2.0.0, it did become possible to mock final classes (although it is an incubating, opt-in feature). This, however, requires a bit of a setup really.
The Idiomatic Mocking Framework for Kotlin
MockK’s main philosophy is offering first-class support for Kotlin features and being able to write idiomatic Kotlin code when using it. Adding MockK is as simple as ever; you only have to add the dependency to your project, and you are set to go.
testCompile "io.mockk:mockk:${mockkVersion}"
class DatabaseTest {
class GenerateRecord { fun generate(): String = "Random String" }
class Dao { fun insert(record: String) = println("""Inserting "$record"""") }
class Service(private val generator: GenerateRecord, private val dao: Dao) {
fun calculate() {
val record = generator.generate()
dao.insert(record)
}
}
val generator = mockk<GenerateRecord>()
val dao = mockk<Dao>()
val service = Service(generator, dao)
@Test
fun insertRecordTest() {
val mockedRecord = "mocked String"
every { generator.generate() } returns mockedRecord
every { dao.insert(mockedRecord) } just Runs
service.calculate()
verifyAll {
generator.generate()
dao.insert(mockedRecord)
}
}
}
Now it is time to talk about such features as captured arguments and mocking.
Syntax In Mockk
First, you need to create a mock:
val mock = mockk<Type>()
Then, you can stub some calls with argument matchers or regular arguments:
every {mock.call(any(), any())} returns 5
Stubbed mocks can now be used in some tested code and called as regular objects.
mock.call(2, 3) // returns 5
After testing is done, you can verify calls again with matchers or regular arguments:
verify {mock.call(2, 3)}
That’s it for the basics, but there is a lot more. Check out the documentation and examples here.
Capturing
Argument capturing can make your life easier if you need to get a value of an argument in every block or verify a block. Let’s say that we have the following class:
There are two ways to capture arguments: using CapturingSlot<Int> and using MutableList<Int>.
CapturingSlot allows you to capture only one value, so it is simpler to use.
val slot = slot<Int>()
val slot1 = slot<Int>()
val mock = mockk<Addition>()
every { mock.call(capture(slot), capture(slot1)) } returns 5
This creates a slot and a mock. You can set expected behavior following way: in case mock.call is called, then arguments are captured to the slot and 5 is returned.
Now for the code being tested:
mock.call(2, 3) // 5 is a result
After executing it, the slot.captured value is equal to the first argument (i.e. 2).
Now you can do some checks. Assert for example:
assertEquals(2, slot.captured)
That is basically it. Working with MutableList is the same, but instead of using a slot in the capture function, MutableList should be used.
val list = mutableList<Int>()
val mock = mockk<Type>()
every { mock.call(capture(list), any()) } returns 5
Conclusion
Mockito felt a bit too Java-ish when using it in a Kotlin project. MockK, being a newer library specifically targeted at Kotlin, felt clean and pleasant to use with excellent documentation.
Top Insights
Manchester City Scores Big with GlobalLogic
AI and MLBig Data & AnalyticsCloudDigital TransformationExperience DesignMobilitySecurityMediaTwitter users urged to trigger SARs against energy...
Big Data & AnalyticsDigital TransformationInnovationRetail After COVID-19: How Innovation is Powering the...
Digital TransformationInsightsConsumer and RetailTop Insights Categories
Let’s Work Together
Related Content
Leveraging SaMD Applications to Improve Patient Care and Reduce Costs
One of the most exciting developments in healthcare is the emergence of Software as a Medical Device (SaMD) as a more convenient and cost-effective means to deliver superior care to the tens of millions of people worldwide who suffer from various health conditions.
Learn More
View on payment industry modernisation: Drivers of change
The payment industry has been going through radical modernisation with multiple regulatory and infrastructure changes over the last five to ten years. The post-pandemic era has accelerated these efforts as consumer behaviour changed significantly during the COVID-19 outbreak. Consumers across the world expect real-time responses in all aspects of digital payment transactions and have adopted … Continue reading MockK Framework for Unit Testing in Kotlin (Android Mobility Development) →
Learn More
The Rise of The Invisible Bank
Banks will power experiences, but everyone will ignore them. Inspiration for this blog title comes from Jerry Neumann, the author of the blog Reaction Wheel, who wrote in 2015 that ‘software eats the world and everybody ignores it’. Neumann also observed that ‘information and communications technology becomes ubiquitous but invisible’ – in other words, … Continue reading MockK Framework for Unit Testing in Kotlin (Android Mobility Development) →
Learn More
GlobalLogic wins at the 2023 Analytics Institute Awards, Dublin
*This blog was updated on Friday 16th June. The team is excited to announce that GlobalLogic was named winners of the Emerging Technology Award at last night’s Analytics Institute Awards! This prestigious award recognises organisations that have successfully employed new technologies such as IoT, Edge Computing, Machine Learning, or RPA. Our submission showcased the successful application of … Continue reading MockK Framework for Unit Testing in Kotlin (Android Mobility Development) →
Learn More
MLOps Principles Part Two: Model Bias and Fairness
Welcome back to the second instalment of our two-part series – MLOps (Machine Learning Operations) Principles. If you missed part one, which focused on the importance of model monitoring, it can be found here. This blog explores the various forms that model bias can take, whilst delving into the challenges of detecting and mitigating bias, … Continue reading MockK Framework for Unit Testing in Kotlin (Android Mobility Development) →
Learn More
The GlobalLogic Academy Programme – a personal, introspective recollection
Ben Graham – Academy 2022 Graduate/Delivery Consultant I am currently in the DevOps capability for consulting and a recent graduate of the Academy 2022 programme which ran from September to December. I’d like to detail my thoughts on the process and share how my fellow graduates and I felt going on this journey. The GlobalLogic … Continue reading MockK Framework for Unit Testing in Kotlin (Android Mobility Development) →
Learn More
Share this page:
-
-
-
-
URL copied!