🤖

[Scala]ユニットテスト等でプライベートメソッドを呼び出すには

2024/04/13に公開

今回はScalaでprivateメソッドを呼び出す方法を簡単にまとめます。
objectとインスタンスそれぞれのやり方を書いていきます。
リフレクションを使いますり

オブジェクトでのやり方

引数なしのメソッドの場合

val method = Example.getClass().getDeclaredMethod("entry1");
method.setAccessible(true)
method.invoke(Example)    
object Example {
    private def entry1() {
        println("entry1 invoked!")
    }
}

Javaのリフレクションの仕組みが使えます。わかりやすいかと思います。
getDeclaredMethod でメソッドを取得、setAccessible でアクセス可能にし、invoke で呼び出しています

引数ありのメソッドの場合

val method = ExampleObj.getClass().getDeclaredMethod("entry2", classOf[String], classOf[String]);
method.setAccessible(true)
val s = method.invoke(ExampleObj, "a", "b").asInstanceOf[String]
println(s)
object ExampleObj {
    private def entry2(x: String, y: String):String = {
        x + y
    }
}

引数なしのときとの変更点があります。
getDeclaredMethod でメソッドを取得するにもメソッドの型の情報についての引数が必要になります。今回は String , String ですので、それらのclassを渡します。
Javaだと String.class の書き方ですが、Scalaは classOf[] を使うようです。
あと、 method.invode がObject型を返してくるので .asInstanceOf[] でキャストしましょう。

インスタンスでのやり方

(後で書きます)

補足

ユニットテストでScalaTestを使っている場合、 invokePrivate を使うとよいでしょう。
(そちらも中で同じようなことをやっているようですが)
例: https://dk521123.hatenablog.com/entry/2023/03/28/003906

参考記事

https://nainaistar.hatenablog.com/entry/2021/05/17/120000
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/reflect/Method.html#invoke-java.lang.Object-java.lang.Object...-

Discussion