티스토리 뷰
TDD에 관심을 가지고 공부 중에 있다. 그래서 개발하면서 JUnit5을 이용한 테스트를 진행하고 있는데, private 메소드에 대한 테스트 방법이 어려워 이것저것 찾고 있다가 정리한다.
그러나! private 메소드를 테스트 하는 것은 antipattern 이라고 한다. 나름대로 정리해봤는데, 내 생각에는 우리가 테스트를 하는 이유에 있는 것 같다.
테스트를 하는 이유는 이 기능이 외부 다른 기능들과 맞물려 있을 가능성이 크고, 변경이 있을 경우 비용이 크게 들어가기 때문에 충분한 테스트를 통해 검증을 해야한다. 하지만 private 메소드의 경우, 해당 메소드는 오로지 동일한 클래스 내에서만 사용되기 때문에, public 메소드를 테스트하면서 자동적으로 private 메소드에 대한 테스트도 이루어져 따로 테스트를 할 필요가 없는 것이다. 즉, private 메소드를 테스트하는 비용이 더 커지는 것이다.
아래는 왜 antipattern 인지에 대한 내용을 포함한 자료이다.
https://stackoverflow.com/questions/47977706/asserting-exceptions-for-private-method-in-junit
https://justinchronicles.net/ko/2014/07/14/dont-do-testing-private-methods/
ㅎㅎ... 꼬박 하루를 private method 와 private field, private method 에서 exception 났을 때의 테스트하는 방법을 열심히 찾았었는데....
이렇게 하나 또 배운다!
어쨌든 ... 그래도 필히 private 메소드/필드/exception에 대해 test 하고 싶을 경우를 대비해 작성한다.
private 메소드 테스트 방법
@Test
void checkIdTest() {
TestService testService = new TestService();
try {
Method method = testService.getClass().getDeclaredMethod("checkId", String.class);
method.setAccessible(true);
boolean result = (Boolean)method.invoke(testService, "ID-01")
Assertions.assertFalse(result);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private 필드 테스트 방법
@Test
void duplicatedIdTest() {
String ID = "ID-01";
TestService testService = new TestService();
try {
//private로 지정된 변수에 접근하는 방법
Field field = testService.getClass().getDeclaredField("idMap");
field.setAccessible(true);
((HashMap)field.get(testService)).put(ID, "value-01");
...
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
...
}
private 메소드 Exception 테스트 방법
@Test
void exceptiondIdTest() {
String ID = "ID-01";
TestService testService = new TestService();
try {
Method method = testService.getClass().getDeclaredMethod("checkId", String.class);
method.setAccessible(true);
method.invoke(testService, ID);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
//privte 메소드인 checkId 에서 발생하는 익셉션은 TestException 클래스이다.
//invoke 에서 InvocationTargetException 이 발생하고,
//해당 익셉션은 e.getCause()를 이용해 테스트하고자 하는 Exception 클래스를 확인할 수 있다.
Assertions.assertInstanceOf(TestException.class, e.getCause());
}
}
'etc' 카테고리의 다른 글
[JAVA] 동작 파라미터화 코드 전달 (0) | 2022.01.17 |
---|---|
[wsl2] 파일 공유 ( Windows 10 <-> Ubuntu 20.04) (0) | 2022.01.17 |
[ junit ] 단위테스트 - @Mock, @InjectMocks (0) | 2021.12.22 |
[ 보안이슈 ] Apache Log4j 취약점 및 해결 방법 (0) | 2021.12.13 |
[windows] windows batch 파일 만들기 (0) | 2021.12.10 |