public이 아닌 생성자에 접근하기(feat.reflection)

murkgom·2021년 6월 30일
0

1. 기본

  • NoArgsConstructor의 접근 제어자는 protected
    - for jpa, mybatis, controller mapping...

  • Anti Setter 전략을 선호

  • 이러한 환경 속에서 테스트 코드를 작성하자!

2. 문제

Service단의 테스트 코드 작성시,

  • 2.1. 객체 생성 필요
  • 2.2. 필요한 값들을 set해줘야 함
  • 2.3. Mock을 활용하자니, 로직 내에서 Setter나 기타 등등 처리가 복잡해질수록 한계가 있음

3. 방안

  • 객체 만들기(Java Reflection 활용)
Class<?> clazz = Class.forName(kr.co.example.MyClass);
Constructor<?> constructor = clazz.getDeclaredConstructor();	
//getConstructor()는 public에만 접근 가능
//parameter가 있는 경우,
//Constructor<?> constructor = clazz.getDeclaredConstructor(parameterType.class);

constructor.setAccessible(true);	//접근 제어자 강제 변경
MyClass myClass = (MyClass)constructor.newInstance();
  • 필드 값 주입하기(ReflectionTestUtils 활용)
ReflectionTestUtils.setField(myClass, "fieldName", "value");
  • 필드 값 주입하기(ReflectionUtils 활용)
Field field = ReflectionUtils.findField(MyClass.class, "fieldName");
field.setAccessible(true);
ReflectionUtils.setField(field, myClass, "value");
  • 메서드 처리하기(ReflectionUtils 활용)
Method method = ReflectionUtils.findMethod(MyClass.class, "methodName");
//Method method = ReflectionUtils.findMethod(MyClass.class, "methodName", "parameter")
	.get();
field.setAccessible(true);
ReflectionUtils.setField(field, myClass, String.class)//마지막 param은 메서드의 parameter type
	.get();		
Result result = ReflectionUtils.invokeMethod(method, myClass);

0개의 댓글