지금껏 테스트 케이스를 작성할 때 public 메소드를 통하여 private 메소드를 테스트 하곤 했는데 private 메소드를 테스트 할 일이 생겨 reflection을 이용하여 유틸 클래스를 작성하게 되었다.
private 접근 제어자가 필드 및 메소드에 존재할지라도 외부 클래스에서 setAccessible(true)로 지정하면 접근이 가능하다.
한 가지 아쉬운 점은 reflection을 이용하여 메소드 테스트를 하고 싶을 때 메소드 이름을 문자열로 넘겨야 한다는 것이다. 이와 같이 메소드 이름을 하드 코딩으로 넘기게 되면 리펙토링에 취약하다는 단점이 있다. (private method 이름을 바꿔버리면? 테스트 실패)
powermock 라이브러리도 private method를 테스트 할 때 메소드 이름을 넘기는 식으로 되어 있던데 안 넘기고 테스트를 할 수 있는 방법이 어디 없을까?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package reflection.test_case; | |
import static org.hamcrest.CoreMatchers.*; | |
import static org.junit.Assert.*; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.junit.Test; | |
/** | |
* @FileName : ReflectionUtils.java | |
* @Project : test_project | |
* @작성자 : nklee | |
* @프로그램설명 : | |
*/ | |
public class ReflectionUtils { | |
/** | |
* <pre> | |
* invokeMethod | |
* private method 테스트를 위한 util | |
* <pre> | |
* @param obj | |
* @param methodName | |
* @param returnType | |
* @param args | |
* @return | |
*/ | |
@SuppressWarnings("unchecked") | |
public static <T> T invokeMethod(Class<?> clazz, String methodName, Class<T> returnType, Object... args) { | |
Class<?>[] parameters = new Class<?>[args.length]; | |
for (int i = 0; i < args.length; i++) { | |
parameters[i] = args[i].getClass(); | |
} | |
try { | |
Object obj = clazz.newInstance(); | |
Method method = obj.getClass().getDeclaredMethod(methodName, parameters); | |
method.setAccessible(true); | |
return (T) method.invoke(obj, args); | |
} catch (Exception ex) { | |
throw new RuntimeException(ex); | |
} | |
} | |
@Test | |
public void accessPrivateMethodTest1() { | |
assertThat("namkyu", is(ReflectionUtils.invokeMethod(UserService.class, "getUser", String.class, "namkyu"))); | |
} | |
@Test | |
@SuppressWarnings("unchecked") | |
public void accessPrivateMethodTest2() { | |
List<String> list = ReflectionUtils.invokeMethod(UserService.class, "getUsers", List.class, "namkyu"); | |
assertThat("kyu", is(list.get(0))); | |
assertThat("kyu2", is(list.get(1))); | |
} | |
} | |
class UserService { | |
public String getUser(String userName) { | |
return makeUser(userName); | |
} | |
private String makeUser(String userName) { | |
return userName; | |
} | |
public List<String> getUsers(String userName) { | |
return makeUserList(); | |
} | |
private List<String> makeUserList() { | |
List<String> list = new ArrayList<String>(); | |
list.add("kyu"); | |
list.add("kyu2"); | |
return list; | |
} | |
} |
'프로그래밍' 카테고리의 다른 글
Tiles definition 렌더링 전 처리 방법 (ViewPreparer 사용) (0) | 2014.04.30 |
---|---|
HTTP request body copy 방법 (0) | 2014.04.29 |
javascript self closing 문제 (2) | 2014.04.16 |
Spring MappingJacksonJsonView modelKey가 하는 역할 (0) | 2014.03.15 |
제너릭 메소드 (0) | 2014.03.01 |
JUnit 테스트 실행 시 src/test/resource 패키지의 설정 파일만 읽어 들일까? (3) | 2014.02.25 |
jackson JSON 사용 중 UnrecognizedPropertyException 발생 시 (2) | 2014.02.15 |
spring security ajax session timeout 체크 방법 (1) | 2014.01.08 |