How to unit test a private method in Kotlin without making it public
Tristan Elliott
Posted on June 4, 2024
Table of contents
My app on the Google play store
My app's GitHub code
The problem I am facing
I have a relatively simple method that I want to test but its private. Why test it in the first place? Well, despite its simplicity it is very important to the project and I want the to be able to test it and ensure that it will run how I want it to. Even if myself or others change it. Further more, if the test fails it will be a sign to me that something has gone wrong and it needs to be fixed before the next release.
The function I want to test:
class TwitchEmoteImpl @Inject constructor(
private val twitchEmoteClient: TwitchEmoteClient,
): TwitchEmoteRepo {
// THE FUNCTION I WANT TO TEST
private fun createMapValue(
emoteValue: EmoteNameUrl,
innerInlineContentMap: MutableMap<String, InlineTextContent>
){
val url = emoteValue.url
val value = InlineTextContent(
Placeholder(
width = 35.sp,
height = 35.sp,
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
)
) {
AsyncImage(
model = url,
contentDescription = stringResource(R.string.moderator_badge_icon_description),
modifier = Modifier
.fillMaxSize()
.padding(2.dp)
)
}
innerInlineContentMap[emoteValue.name] = value
}
}
- The obvious question is,
how do I test a private method without making it public?
. The answer is,Dependencies!!!!!
- To clarify, we take all of the logic out of this private method, put it into a public dependency that we can then test. Our updated code will look like this:
class TwitchEmoteImpl @Inject constructor(
private val twitchEmoteClient: TwitchEmoteClient,
private val emoteParsing:EmoteParsing = EmoteParsing()
): TwitchEmoteRepo {
private fun createMapValue(
emoteValue: EmoteNameUrl,
innerInlineContentMap: MutableMap<String, InlineTextContent>
){
// WE CAN NOW UNIT TEST THE EmoteParsing CLASS
emoteParsing.createMapValueForComposeChat(
emoteValue,
innerInlineContentMap
)
}
}
- As you can see the dependency (
emoteParsing
) we created is literally just a clone to help us aid in testing:
class EmoteParsing {
fun createMapValueForComposeChat(
emoteValue: EmoteNameUrl,
innerInlineContentMap: MutableMap<String, InlineTextContent>
){
val url = emoteValue.url
val value = InlineTextContent(
Placeholder(
width = 35.sp,
height = 35.sp,
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
)
) {
AsyncImage(
model = url,
contentDescription = stringResource(R.string.moderator_badge_icon_description),
modifier = Modifier
.fillMaxSize()
.padding(2.dp)
)
}
innerInlineContentMap[emoteValue.name] = value
}
}
- We can now unit test this createMapValueForComposeChat() function through the EmoteParsing class.
Why not just make it public?
- You obviously could make the method public. However, this would give developers(myself or others) the ability to use the code not as it was intended to. Essentially, increasing the scope of the class. By keeping the method private we are establishing clear boundaries between classes and leave smaller possibilities of misuses.
Conclusion
- Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.
💖 💪 🙅 🚩
Tristan Elliott
Posted on June 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
android Quick example of creating a custom Kotlin coroutine and scoping it to a Android service.
November 21, 2024
android My notes on Android optimization. Part 2. Quick example of benchmarking Kotin regular expressions
September 7, 2024
android Getting the height of Android device independent of pixel densities in Jetpack Compose
July 18, 2024