LivBanana
LivBanana

Reputation: 381

How to test a private function in kotlin?

I have two objects remote model and domain model

Remote model

data class InstanceRemoteModel (
    val id: String,
    val containers: List<Container>,
    val operations: List<Operation>
)

data class ContainerRemoteModel (
    val id: String,
    val capacity: Long
)

data class OperationRemoteModel (
    val id: String,
    val weight: Long,
    val containerId: String
)

Domain Model

data class Instance (
    val id: String,
    val containers: Map<String, Container>,
    val operations: Map<String, Operation>
)

data class Container (
    val id: String,
    val capacity: Long
    val total_weight: Long
)

data class Operation (
    val id: String,
    val weight: Long,
    val container: Container
)

And then I have a mapper that map objects from remote model to domain model. Here I will concentrate on mapping the containers. Note that a Container object in the domain model have different properties than ContainerRemoteModel. The same thing is done with the operations.

object Mapper {
  fun toDomainModel(remoteInstance: InstanceRemoteModel): Instance {
    val containers : Map<String, Container> = mapContainers(remoteInstance)
    val operations : Map<String, Operation> = mapOperations(remoteInstance)
    return Instance(remoteInstance.id,containers,operations)
  }



  private fun  mapContainers(remoteInstance: InstanceRemoteModel) : Map<String, Container> {
    //do some computations
    val containers : List<Container> = remoteInstance.containers.map { cont -> Container(...)}
    return containers.associateBy({ it.id }, { it }
  }

  private fun mapOperations(remoteInstance: InstanceRemoteModel): Map<String, Operation> {
    ...
  }
}

My question is : How to properly test the mapper? Note that mapOperations and mapContainers are private functions.

Upvotes: 1

Views: 5823

Answers (1)

Naor Tedgi
Naor Tedgi

Reputation: 5707

in unit testing, you need to test only the public methods! if a private function isn't covered by testing the class public functions then that function is an island and no one using it and the compiler will alert about it.

been says that if you still want to test this function

you can use reflection to access any field you want

by adding this dependency

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-reflect</artifactId>
    <version>1.4.20</version>
    <scope>runtime</scope>
</dependency>

then you can test it

class MapperTest : TestCase(){

    @Test
    fun `test private method`(){
        val input = InstanceRemoteModel("test", emptyList(), emptyList())
        val returnValue = Mapper.invokePrivateFunction("mapContainers",input) as Map<String, Container>
        assert(returnValue.isEmpty())
    }

    inline fun <reified T> T.invokePrivateFunction(name: String, vararg args: Any?): Any? =
        T::class
            .declaredMemberFunctions
            .firstOrNull { it.name == name }
            ?.apply { isAccessible = true }
            ?.call(this, *args)
}

Upvotes: 2

Related Questions