Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing extension functions inside classes

If we want to test an extension function on a type, we can create an instance of this type, call the function and check the returned value. But what about testing extension functions defined inside classes?

abstract class AbstractClass<T> {
    fun doStuff(): T = "Hello".foo()

    abstract fun String.foo(): T
}

class SubClass1: AbstractClass<Int>() {
    override fun String.foo(): Int = 1
}

class SubClass2: AbstractClass<Boolean>() {
    override fun String.foo(): Boolean = true
}

How do we test the logic of the methods foo() in classes SubClass1 and SubClass2? Is it even possible?

I know I can change the design to test it. Two possibilities have occurred to me:

  1. Don't use extension functions. ¯\_(ツ)_/¯

    abstract class AbstractClass<T> {
        fun doStuff(): T = foo("Hello")
    
        abstract fun foo(string: String): T
    }
    
    class SubClass1: AbstractClass<Int>() {
        override fun foo(string: String): Int = 1
    }
    

    Then we can create an object SubClass1, call foo() and check the returned value.

  2. Create additional extension functions with internal visibility just to test the logic.

    class SubClass1: AbstractClass<Int>() {
        override fun String.foo(): Int = internalFoo()
    }
    
    internal fun String.internalFoo(): Int = 1
    

    Then we can create an object String, call internalFoo() and check the returned value. However, I don't like this solution because we could change the body of override fun String.foo(): Int and our test would pass.

So, is it possible to test extension functions inside classes? If not, how would you change your design in order to test their logic?

like image 804
JavierSA Avatar asked Jun 05 '18 14:06

JavierSA


People also ask

How extension function works internally?

An extension function can go anywhere a regular function can. It may be top-level (equivalent to java static), in a companion object (act like static but not equivalent to java static), or as a member of a class (not static at all).

How do you call a function with an extension?

Example of extension function declaration and its useisExcellent() and call it from the main() function. The declare Student. isExcellent() function is known as extension function, where Student class is known as receiver type. The above example only demonstrates about how to declare an extension function.

What is true about extension functions in Kotlin?

Extension functions are a cool Kotlin feature that help you develop Android apps. They provide the ability to add new functionality to classes without having to inherit from them or to use design patterns like Decorator.

When would you use Kotlin extension function?

In particular, Kotlin extensions let you add functions to a class that you cannot modify. By using them, you will be able to call these new functions as if they were part of the original class. Similarly, you can use this mechanism to add new properties to existing classes. You can also extend Kotlin companion objects.


1 Answers

Since tests should be written from the client's perspective, I'm not sure it would be a valid test. But I did come up with one way to test it.

@Test
fun `test extension function`() {
    var int = 0

    SubClass1().apply {
        int = "blah".foo()
    }

    assertThat(int, `is`(1))
}
like image 62
David Avatar answered Sep 26 '22 02:09

David