[자바, Java] JUnit - private 변수, 메서드 테스트하기

JUnit private member 접근 방법


자바에서 테스트 코드 작성 시, private 변수 또는 메서드를 테스트해야 하는 경우가 생길 수 있다.

물론 최대한 private 멤버를 끌어들이지 않도록 애초에 설계를 잘 하는 것이 우선이겠지만, 알아두도록 하자.


1. Private Variable 접근 방법

  • public class Calculate {
        private final int a;
        private final int b;
          
        public Calculate(int a, int b) {
            this.a = a;
            this.b = b;
        }
    }
      
    // ==================================== //
      
    class CalculateTest {
        @Test
        void private_num_test() {
            Calculate calculate = new Calculate(2, 3); // a = 2, b = 3
            int a = 0;
            int b = 0;
            try {
                Field field = calculate.getClass().getDeclaredField("a"); // Field를 생성하고 내가 얻고자하는 변수명을 입력해준다.
                field.setAccessible(true); // 해당 변수를 field에 담았으니 접근 가능하게 만든다.
                a = (int) field.get(calculate); // field.get(생성한 클래스명)을 통해 얻고자했던 private value를 얻어주면 된다.
          
                Field field2 = calculate.getClass().getDeclaredField("b");
                field2.setAccessible(true);
                b = (int) field2.get(calculate);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
              
            assertThat(a + b).isEqualTo(5); // 테스트 성공
        }
    }
      
    // 테스트 성공
    
  • 여기서 private 변수를 여러개 뺄 때 코드가 지저분해진다.

    • 그래서 내가 개인적으로 쓰는 방법이 있다. (더 좋은 방식이 있다면 알려주십쇼.)

    • public class Calculate {
          private final int a;
          private final int b;
              
          public Calculate(int a, int b) {
              this.a = a;
              this.b = b;
          }
      }
          
      // ==================================== //
          
      class CalculateTest {
          @Test
          void private_num_test() {
              Calculate calculate = new Calculate(2, 3);
              int a = (int) getPrivateVariable(calculate, "a");
              int b = (int) getPrivateVariable(calculate, "b");
                  
              assertThat(a + b).isEqualTo(5);
          }
              
          private Object getPrivateVariable(Object object, String variableName) {
              try {
                  Field field = object.getClass().getDeclaredField(variableName);
                  field.setAccessible(true);
                  return field.get(object);
              } catch (NoSuchFieldException | IllegalAccessException e) {
                  throw new RuntimeException(e);
              }
          }
      }
          
      // 테스트 성공
      
      • 이런식으로 형변환을 해서 반환 받게끔 메서드를 구현해서 사용한다.

        • 이러면 몇개를 빼든, 여러 타입을 빼든 이 메서드 하나로 전부 커버가 가능하다.

2. Private Method 접근 방법

  • public class Calculate {
        private int add(int a, int b) {
            return a + b;
        }
    }
      
    // ========================================= //
      
    class CalculateTest {
        @Test
        @DisplayName("더하기")
        void add() {
            Calculate calculate = new Calculate();
            int sum = 0;
            try {
                // getDeclaredMethod 첫번째 인자에 메서드 이름, 두번째 인자부턴 메서드의 매개변수 타입을 순서대로 지정해준다.
                Method method = calculate.getClass().getDeclaredMethod("add", int.class, int.class);
                method.setAccessible(true); // 해당 메서드에 접근 가능하도록 설정
                sum = (int) method.invoke(calculate, 3,4); // 해당 메서드를 인자 전달과 함께 호출하고, 값을 반환받는다.
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
              
            assertThat(sum).isEqualTo(7); // 테스트 성공
        }
    }
      
    // 테스트 성공
    
    • 여기도 마찬가지로 private 메서드를 여러개 호출할 때 코드가 지저분해진다.

      • 그래서 내가 개인적으로 쓰는 방법이 있다.

      • public class Calculate {
            private int add(int a, int b) {
                return a + b;
            }
        }
              
        // ===================================== //
              
        class CalculateTest {
            @Test
            @DisplayName("더하기")
            void add() {
                Calculate calculate = new Calculate();
                int sum = (int) getPrivateMethodResult(calculate, "add", 3, 4);
                assertThat(sum).isEqualTo(7);
            }
                  
            private Object getPrivateMethodResult(Object object, String methodName, int n1, int n2) {
                try {
                    Method method = object.getClass().getDeclaredMethod(methodName, int.class, int.class);
                    method.setAccessible(true);
                    return method.invoke(object, n1, n2);
                } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
              
        // 테스트 성공
        
        • 이런식으로 같은 private method 나 같은 매개변수 타입과 순서를 가진 메서드를 추가로 호출할 때, 형변환 해서 갖다 쓸 수 있도록 구현한다.




© 2021. All rights reserved.

----------Powered by Hydejack----------

Jun's Development Blog