JMockitでprivateメソッドを呼ぶ方法
出向先でJunitを使う機会があったので、コンパイルエラーしやすい箇所をここで備忘録として書き込むようにしておく。
package test;
public class Test1 {
String runSample() { String runSample() {
// 未実装
return null;
}
private int numberReturn(int a,int b) {
int result;
result = a + b;
return result;
} void main() {
int sum = 0;
sum = numberReturn(2,3);
}}
Test1.javaこのソースにおけるnumberReturnメソッドをモック化して一度呼び出したい場合
package test;
import static org.hamcrest.CoreMatchers.*;import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import mockit.Mock;import mockit.MockUp;
class Test1Test {@Test
public void test_numberReturn() {
new MockUp<Test1>() {
@Mock()
public int numberReturn(int a,int b) {
return a+b;
}
};
Test1 s = new Test1();int a = s.numberReturn(3,4);
assertThat(a, is("1"));
}
}
上記のように記載すると37行目のs.numberReturn(3,4);でメソッドが不可視ですというエラーが出力される。
この場合privateメソッドはモックとして呼ばれないので、対象となるprivateメソッドをgetDeclaredMethodでインスタンス化してからsetAccessibleでアクセス出来るように設定させる。
その後はインスタンス化したprivateメソッドをinvokeで呼び出すようにする。
こうすることでprivateメソッドをモックとして呼び出すことに成功できる。
package test;
import static org.hamcrest.CoreMatchers.*;import static org.junit.Assert.*;
import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;
import org.junit.jupiter.api.Test;class Test1Test {
@Testpublic void test_numberReturn() throws
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException
{
Test1 s = new Test1();
Method method = Test1.class.getDeclaredMethod
("numberReturn", int.class, int.class);
method.setAccessible(true);
int a = (int)method.invoke(s,3,4);
assertThat(a, is("1"));
}
}
追記:このgetDeclaredMethodメソッドはアクセス権限が制限されているメソッドをアクセスする為に使う。
似たようなメソッドとしてはgetDeclaredConstructorメソッドでこちらはprivate修飾子が付いたコンストラクタをインスタンスとして生成するのに使われる。