How to use kotlin functional programming to access a property - unit-testing

I currently have the following function:
fun createMask(mask : String){
val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
ssnField.hint = mask
}
To unit test this I want to wrap the untestable code within createMask into a closure. (The untestable code is the view layer logic that's difficult to instantiate and execute in a unit test.) Here is what I want to do in pseudo code:
createMask(closure, mask : String){
closure = mask // closure function returns pointer to property (depending on closure return type, might need to use setter: closure.set(mask))
}
With the above, the caller then does:
fun caller(){
createMask((){
val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
return ssnField.hint
}, "xxx-xx-xxx")
}
How do do what is expressed in pseudo code work in kotlin?

You can return a reference of the property if you make createMask accept a parameter of type () -> KMutableProperty0<String>. Then you can call the set method:
fun createMask(mask : String, block: () -> KMutableProperty0<String>) {
block().set(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
ssnField::hint
}
Alternatively, use (String) -> Unit to represent "any function that takes a string", if you want to allow callers to pass any function that has the "form" of a setter.
fun createMask(mask : String, block: () -> (String) -> Unit) {
block()(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
ssnField::hint.setter
}
Note that this method involves reflection, which may not be desirable. Alternatively, you can accept a closure that takes the string to be set, and let the caller set it in the closure:
fun createMask(mask: String, block: (String) -> Unit) {
block(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
// note that rather than responsible for returning a property, the caller
// is responsible for setting "it" to the property
ssnField.hint = it
}
(I'm assuming createMask does more than just setting a property. Otherwise it is quite pointless...)

Related

How do we verify method that has lambda function as its argument?

So I have this main() method that calls printResult() method and the printResult() has a lambda argument on second parameter like this:
class SomeClass() {
fun main(value: Int) {
printResult(value){ it ->
it + it
}
}
fun printResult(value: Int, sum: (Int) -> Int) {
val result = sum(value)
println(result)
}
}
Then in the unit test, I want to verify that every time the main() method is called, the printResult() should be invoked as well. So I write the unit test like this:
#Test
fun testMain_shouldInvokePrintResult() {
someClass.main(10)
verify(someClass).printResult(10){ any() }
}
I don't know what argument I should pass for printResult() method, that's why I used any(). But when I run the test, the compiler said:
Argument(s) are different! Wanted:
someClass.main(
10,
() (kotlin.Exception /* = java.lang.Exception */) -> kotlin.Unit
);
-> at com.mydomain.test.testMain_shouldInvokePrintResult(SomeClassTest.kt:49)
Actual invocations have different arguments:
someClass.main(
10,
() (kotlin.Exception /* = java.lang.Exception */) -> kotlin.Unit
);
-> at com.mydomain.SomeClass.printResult$lambda-27(SomeClass.kt:20)
So the compiler basically said different arguments but showed me no different on both invocation. What should I do? any help would be appreciated..
It solved. So my colleagues told me to use any() inside parenthesis instead of the curly brackets. So it would be like this:
#Test
fun testMain_shouldInvokePrintResult() {
someClass.main(10)
verify(someClass).printResult(10, any())
}

Get private method with reflection in order to pass it to a higher order function in Kotlin

I'm having a hard time trying to get a private method in Kotlin using reflection in order to pass it as a parameter to a higher order function, here is what I got and what I need to do:
The function that gets the private method, probably what I should change or fix:
inline fun <reified T> T.getPrivateFunc(name: String): KFunction<*> {
return T::class.declaredMemberFunctions.first {
it.name == name
}.apply {
isAccessible = true
}
}
This is the high order function I have:
class MyService {
fun myHigherOrderFunction(action: () -> Unit) { /*...*/ }
}
These are the class and the private method I need to get somehow:
class SystemUnderTest {
fun privateFunc() { /*...*/ }
}
Finally a unit test where I I'm trying to make sure the proper method is passed to the high order function, I omitted details for simplification:
// ...
val serviceMock = MyService()
val sut = SystemUnderTest()
// Here is what I'm trying to accomplish
val privateMethod = sut.getPrivateMethod("privateFunc")
service.myHighOrderFunction(privateMethod)
// In the above line I get a compilation error: required () - Unit, found KFunction<*>
service.myHigherOrderFunction(privateMethod as () -> Unit)
// In the above line I get the following runtime error:
// ClassCastException: kotlin.reflect.jvm.internal.KFunctionImpl cannot be cast to kotlin.jvm.functions.Function1
I know the test can be done having the privateFunc as public and maybe annotating it with #VisibleForTesting, but what I want is to avoid compromising the design as long as I can.
Any ideas? Thanks in advance!
I don't think KFunction and KCallable have any notion of a bound receiver, so they are not invokable (have no operator fun invoke), and therefore don't qualify as functions. So I think you have to wrap the KFunction object in a function to be able to pass it to your higher order function. To call a KFunction, you pass the instance of the receiver class as the first argument.
val serviceMock = MyService()
val sut = SystemUnderTest()
val privateMethod = sut.getPrivateMethod("privateFunc")
service.myHighOrderFunction { privateMethod.call(sut) }
Edit: To internalize the creation of the wrapped function, you could do this:
inline fun <reified T> T.getZeroArgPrivateMethod(name: String): () -> Unit = {
T::class.declaredMemberFunctions.first {
it.name == name
}.apply {
isAccessible = true
}.call(this)
}
//...
val serviceMock = MyService()
val sut = SystemUnderTest()
val privateMethod = sut.getZeroArgPrivateMethod("privateFunc")
service.myHighOrderFunction(privateMethod)

Cast of the List<String> to List<T> in Kotlin

I need to create a generic method that splits a string and casts values
inline fun <reified T: Any> convertFromString(myString: String) : List<T>{
val castedList = ArrayList<T>()
for(item in myString.split(";")){
castedList.add(item as T)
}
return castedList
}
I call this method convertFromString<Int>("1;2;3;4;5;6") and expect to have output List<Int> but it fails during the cast item as T.
How can I cast all values to generic T?
I would rather suggest you to supply a transformation function, e.g.
inline fun <T: Any> convertFromString(myString: String, transformation: (String) -> T)
= myString.split(";")
.map(transformation)
.toList()
Note that you can't cast the String to anything else then String that is why item as T will not work. With the transformation function you ensure that it is transformed correctly (as long as you do not use item as T as the transformation ;-)).
Some sample usages/transformation functions could be:
val doubleList = convertFromString("123;123") { it.toDouble() }
val intList = convertFromString("123;123") { it.toInt() }
val objList = convertFromString("data=123;data=444") { yourParser.parse(it) }
Additionally with that approach you do not require the reified anymore. The inline however is still useful for any function containing a lambda function.

What is concise way of deep-copying a 2D MutableList?

The element already implemented deep copying.
fun <T : DeepCopiable> f(a: MutableList<MutableList<T>>) {
val copied = a.map { it.map { it.deepCopy() }.toMutableList() }.toMutableList()
...
}
I am using this kind of code, but it seems verbose.
Due to restrictions in the type system, this problem cannot be generalized to a single functon without bypassing type safety (and due to JVM type erasure you definitely don't want to go that rabbit hole when generics are involved¹).
However, you can write a chain of extension functions implementing a deep-copy pattern, delegating to the previous function for every increase in dimension, in a type safe matter:
private typealias I<E> = Iterable<E>
private typealias Copy<E> = (E) -> E
private inline fun <T, R> I<T>.mapToMutable(transform: (T) -> R): I<R> = mapTo(mutableListOf(), transform)
fun <E> I<E>.deepCopy1(c: Copy<E>) = mapToMutable { c(it) }
fun <E> I<I<E>>.deepCopy2(c: Copy<E>) = mapToMutable { it.deepCopy1(c) }
fun <E> I<I<I<E>>>.deepCopy3(c: Copy<E>) = mapToMutable { it.deepCopy2(c) }
fun <E> I<I<I<I<E>>>>.deepCopy4(c: Copy<E>) = mapToMutable { it.deepCopy3(c) }
fun <E> I<I<I<I<I<E>>>>>.deepCopy5(c: Copy<E>) = mapToMutable { it.deepCopy4(c) }
Due to JVM type erasure, the functions need different names (#JVMName does not help due to type interference ambiguity²). Type aliases are used to prevent horizontal space explosion³, and the function set is uncoupled from the deep-copiable interface via a generic copy function parameter.
Example usage:
fun main(args: Array<String>) {
data class IntHolder(var value: Int)
val original = List(3) { a ->
List(3) { b ->
IntHolder(a + b)
}
}
val copied = original.deepCopy2 { it.copy() }
original[0][0].value = 18258125
println("original=$original")
println("copied =$copied")
}
->
original=[[IntHolder(value=18258125), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]
copied =[[IntHolder(value=0), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]
[1]: Because generic type casts are performed by the compiler at runtime, a cast from List<Foo> to List<Baz> will always succeed at runtime, but fail later upon access of the casted list. Implementing mentioned magic "single function" is possible, but the slightest of error would result in a returned data structure that fails seemingly "random" upon access with class cast exceptions.
[2]: A value of type Iterable<Iterable<Foo>> satisfies both
fun <T> Iterable<T>.baz() (T = Iterable<Foo>) and
fun <T> Iterable<Iterable<T>.baz() (T = Foo)
Due to this, the compiler would not be able to determine the right method to use if all methods in the chain have the same function name, but different JVM names.
[3]:
Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<ithinkyougetthepoint>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Here is a simple deep copy example by using java.lang.reflect.Array & java.lang.Cloneable.
Noet: the clone method performs a shallow copy of this object, not a deep copy operation, but you can override the clone method to provide a deep copy operation, for example:
val list = mutableListOf(mutableListOf(arrayOf(1)))
val copied = list.deepCopy()
println(copied !== list) //true: not the same
println(copied.map{it.map{it.toList()}} == list.map{it.map{it.toList()}})
// ^---true: content equals
// v--- Array is cloned, since it has implemented Cloneable
println(copied[0][0] !== array[0][0]) // true
typealias NativeArray = java.lang.reflect.Array
#Suppress("UNCHECKED_CAST")
fun <T> T.deepCopy(): T {
return when (this) {
is Array<*> -> {
val type = this.javaClass.componentType
NativeArray.newInstance(type, size).also {
this.forEachIndexed { i, item ->
NativeArray.set(it, i, item.deepCopy())
}
} as T
}
is MutableList<*> -> this.mapTo(mutableListOf()) { it.deepCopy() } as T
is List<*> -> this.map { it.deepCopy() } as T
is Cloneable -> this.javaClass.getDeclaredMethod("clone").let {
it.isAccessible = true;
it.invoke(this) as T
}
else -> this
}
}

Kotlin Anonymous Function Parameter Unit Testing

As per Kotlin Unit Testing for Function Parameter and Object, we could test the function variable funcParam, as it is an object function variable.
However if code is written using anonymous/inlining function parameter (which is a very nice Kotlin feature, that allow us to eliminate unnecessary temp variable for it)...
class MyClass1(val myObject: MyObject, val myObject2: MyObject2) {
fun myFunctionOne() {
myObject.functionWithFuncParam{
num: Int ->
// Do something to be tested
myObject2.println(num)
}
}
}
class MyObject () {
fun functionWithFuncParam(funcParam: (Int) -> Unit) {
funcParam(32)
}
}
How to write my unit test that test this part of code?
num: Int ->
// Do something to be tested
myObject2.println(num)
Or the inlining of the function parameter (as above) is something not good for unit testing, and hence should be avoided?
After a while discover the way to test it is to use Argument Captor.
#Test
fun myTest() {
val myClass1 = MyClass1(mockMyObject, mockMyObject2)
val argCaptor = argumentCaptor<(Int) -> Unit>()
val num = 1 //Any number to test
myClass1.myFunctionOne()
verify(mockMyObject).functionWithFuncParam(argCaptor.capture())
argCaptor.value.invoke(num)
// after that you could verify the content in the anonymous function call
verify(mockMyObject2).println(num)
}
For more info, refer to https://medium.com/#elye.project/how-to-unit-test-kotlins-private-function-variable-893d8a16b73f#.1f3v5mkql