Mockito cannot mock because : final class in Kotlin
In this blog, I will talk about using Mockito to test final classes in Kotlin. Why is this an issue, which made me write a blog on it. So, before delay let me get started.
But, Firstly let me help you start with a small example of using Mockito.To integrate Mockito in our project we will add the following in our app's build.gradle file,
testImplementation 'org.mockito:mockito-core:2.19.0'
Then, In our src -> main -> java -> apps_package_name, we will create a file which we are going to test called Utility.kt
class Utility {
fun getSum(a: Int, b: Int): Int = a + b
}
Here, we will test the getSum() function which takes two integer parameter and returns it's sum.
Now, to start its local unit testing, we need to create a file called UtilityTest.kt file in test package.
class UtilityTest{
@Test
fun providedNumber_isSum_true(){
val mockUtil = mock(Utility::class.java)
`when`(mockUtil.getSum(1,2)).thenReturn(3)
val actualResult = mockUtil.getSum(1,2)
assertEquals(3, actualResult)
}
}
In the above snippet,
- @Test annotation means that the function can be exectuted as a test.
- using mock(...), we actually are mocking the Utility class file at the runtime.
- Now, we are running the getSum() from Utility class and returning the result.
- Now, we assign the result to a actualResult variable from mockUtil.getSum(..) . This will make the value 3 as because we passed 1,2.
- Lastly, we pass assertEquals() to check if the expected output is same as desired output.
Now, when we run the test we should get the test has passed as sum of 1 and 2 is always 3. But, when we run this we bump into an error,
Why is this? The test case which we wrote it was correct but the error shows that we can't mock the final class.
This is because,
All Kotlin Classes are Final by default.
Now, there are two ways to do it. Let's talk about them one by one.
- Firstly we can make the Utility class open and then can we test the class using the above code.This can be a problem as because now we have to change the code base.
- Secondly and most importantly, Mockito 2.10 provided a new update where we can mock the final classes.
Let's talk about it in detail.In the project, under src->test folder create a resources directory. Inside it create a new directory called mockito-extensions .
Inside the mockito-extensions directory we create a text file called
org.mockito.plugins.MockMaker
and add mock-maker-inline in the file.
That is it. Now when we run the above test which we created will throw an output,
Voila, our test has passed.
But, what magic did this one line did ?
This indicated Mockito Framework that we can now mock any final classes.
Note: We can also use all-open plugin to do the same and it will also help to mock the final classes.
Happy Coding :)