くうと徒然なるままに

モバイルアプリを作りながらバックエンドも作っています。

kotlin で lambda 関数の呼び出しログと回数を記録できる便利クラスを作ってみた。

Unit Test 等で lambda 関数 を使用しているところで呼び出しログと呼び出し回数を記録したいことはたまによくあると思います。

そこで、記録できる便利クラスを書いてみました。

機能

  • 呼び出しログの記録
  • 回数の記録と検証(指定された回数呼び出されてなかったらエラーになるように。

AwaitableLambda.kt

import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException

class AwaitableLambda<T>(
    count: Int = 1,
    val Func: (T) -> Unit = {}
) : (T) -> Unit {

    private val latch = CountDownLatch(count)

    private val _callStack = Stack<T>()
    val callStack: List<T> = _callStack

    fun isComplete(count: Long = 1, unit: TimeUnit = TimeUnit.SECONDS): Boolean {
        if (!latch.await(count, unit)) {
            throw TimeoutException()
        }
        return true
    }

    override fun invoke(p1: T) {
        Func(p1)
        latch.countDown()
        _callStack.push(p1)
    }
}

一応、Unit Test も雑に書いてみた

internal class awaitableLambdaTest {
    @Test
    fun 関数が一度呼び出される検証を行う() {
        val awaitableLambda = AwaitableLambda<String>()

        awaitableLambda("")

        assert(awaitableLambda.isComplete())
    }

    @Test(expected = TimeoutException::class)
    fun 関数が一度も呼び出されないテスト() {
        val awaitableLambda = AwaitableLambda<String>()
        awaitableLambda.isComplete()
    }

    @Test
    fun 関数が過剰に呼び出されるテスト() {
        val awaitableLambda = AwaitableLambda<String>()
        awaitableLambda("")
        awaitableLambda("")
    }

    @Test
    fun 初期状態ではコールスタックに何も積まれていないテスト() {
        val awaitableLambda = AwaitableLambda<String>()
        Assert.assertEquals(0, awaitableLambda.callStack.count())
    }

    @Test
    fun コールスタックに1つ積まれるテスト() {
        val awaitableLambda = AwaitableLambda<String>()
        awaitableLambda("Hello")
        Assert.assertEquals("Hello", awaitableLambda.callStack.elementAt(0))
    }

    @Test
    fun コールスタックに複数個積まれるテスト() {
        val awaitableLambda = AwaitableLambda<String>()
        awaitableLambda("Hello")
        awaitableLambda("Work")
        Assert.assertEquals("Hello", awaitableLambda.callStack.elementAt(0))
        Assert.assertEquals("Work", awaitableLambda.callStack.elementAt(1))
    }
}