[210530] junit에서 private 메소드 테스트하기 - reflection 사용
.
테스트 코드를 작성하던 중, 다른 클래스에 있는 private 메소드를 테스트해야 하는 상황이 발생했다. 테스트 때문에 메소드를 public으로 지정할 수 없었고, 테스트 코드에 메소드를 새로 생성할 수도 없었다.
구글링을 통해 reflecton을 사용해서 private 메소드에 접근할 수 있다는 사실을 알게 되었다.
java.lang.Reflection
런타임 중에 메소드나 클래스를 검사하고 작동시킬 수 있게 해주는 API이다. 리플랙션 객체를 사용해서 리플렉션 객체가 가지고 있는 클래스나 메소드의 정보를 알아낼 수 있다. 또한 런타임 중에 메소드를 실행할 수도 있다.
내 경우에는 아래와 같이 코드를 작성해서 private 메소드를 테스트할 수 있었다.
LoginController loginController = new LoginController();
AdminBean testAdminBean = new AdminBean(0, "user_id","pw","user_name");
// 1. Method 객체 선언
Method method = loginController.getClass().getDeclaredMethod("getAdminBeanInDatabase", AdminBean.class);
// 2. accessible flag 설정
method.setAccessible(true);
// 3. 메소드 사용
Optional<AdminBean> optional = (Optional<AdminBean>) method.invoke(loginController, testAdminBean);
1. Method 객체 선언
Method method = loginController.getClass().getDeclaredMethod("getAdminBeanInDatabase", AdminBean.class);
먼저 Method 객체를 선언하였다.
(java.lang.reflect.Method :클래스나 인터페이스의 메소드에 접근하거나 정보를 가져올 수 있게 해주는 클래스)
사용해야 할 private 메소드가 있는 클래스인 loginController에 getClass()를 사용해서 클래스 객체를 가져오고, getDeclaredMethod()로 해당 클래스에 선언된 메소드를 가져온다. 매개변수로 메소드 이름(getAdminBeanInDatabase), 메소드의 return parametertype(AdminBean.class)을 넘겼다.
2. accessible flag 설정
method.setAccessible(true);
setAccessible은 해당 객체(메소드, 필드가 될 수도 있다.)의 접근 지정자와 관계없이 리플렉션 객체에 접근할 수 있게 해준다. method를 사용하기 위해서 매개변수의 값을 true로 준다.
3. 메소드 사용
Optional<AdminBean> optional = (Optional<AdminBean>) method.invoke(loginController, testAdminBean);
method.invoke()를 사용해서 메소드를 실행할 수 있다. 매개변수로 메소드가 선언된 클래스 객체와, 사용할 메소드에 필요한 매개변수 값을 넘겨준다. 내 경우에는 실행해야 할 메소드의 return 값이 Optional이었기에 Optional 객체를 사용해서 return 값을 받아왔다.
- 참고 자료
https://www.geeksforgeeks.org/reflection-in-java/
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html