DEV Community

Cover image for Unit testing private methods inside of Android with Kotlin
Tristan Elliott
Tristan Elliott

Posted on • Edited on

Unit testing private methods inside of Android with Kotlin

Table of contents

  1. How to unit test a private method
  2. Explanation

My app on the Google play store

GitHub code:

2024-06-03 update: To anyone reading this

  • I don't like this post that I created. I would recommend you leave here and read my updated one.

  • You can find the updated one : HERE

How to unit test a private method inside of a ViewModel?

  • Obviously you can't unit test a method that you can't directly access. By definition, we can't access a private method. However, there are two ways to work around this:

1) Make the method public
2) Keep the method private but put the logic inside of a dependency's public method

  • Since Make the method public is rather self explanatory, I will be explaining the second method

Adding the logic inside of a dependency's public method

  • Let's assume that this is our private method logic:
class StreamViewModel @Inject constructor(){

fun callingThePrivateMethodFromView(a:Int,b:Int){
        privateMethod(a,b)
    }

 private fun oldPrivateMethod(a:Int,b:Int): Int{
        //pretend this is advanced logic
        val answer =(a/b) * 45 -9
        return answer
    }
}

Enter fullscreen mode Exit fullscreen mode
  • Now because of the advanced logic inside of the privateMethod() method we want to be able to unit test it. To determine that the method is deterministic and does what we expect. Again, we can't do that with the private method so we have to do a few steps of refactoring.

  • 1) create a new object to act as the dependency for a ViewModel

class TokenMonitoring constructor(){

}

Enter fullscreen mode Exit fullscreen mode
  • 2) put advanced logic into public method
class TokenMonitoringconstructor(){
 fun privateMethod(a:Int,b:Int): Int{
        //pretend this is advanced logic
        val answer =(a/b) * 45 -9
        return answer
    }

}

Enter fullscreen mode Exit fullscreen mode
  • 3) Inject into constructor and call from dependency
class StreamViewModel constructor(
private val tokenMonitoring: TokenMonitoring= TokenMonitoring()
){

fun callingThePrivateMethodFromView(a:Int,b:Int){
        oldPrivateMethod(a,b)
    }
}

private fun oldPrivateMethod(a:Int,b:Int): Int{

        return tokenMonitoring.privateMethod(a,b)
    }

Enter fullscreen mode Exit fullscreen mode

How does this help with the unit testing?

  • The unit testing of privateMethod() is now done through the TokenMonitoring() class. This means that we can unit test the advanced logic by accessing tokenMonitoring.privateMethod(a,b). Which has the added factor of us now also being able to control the TokenMonitoring() when testing StreamViewModel

Isn't this just the same as making it public?

  • No! Making the method public would also give the View access to the method. By adding the logic into a public method of a dependency and then injecting that dependency, the view does not have access to this method and then old method can still stay private

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.

Top comments (0)