[java] 개인 함수, 개인 메서드, 필드 또는 내부 클래스가있는 클래스를 어떻게 테스트합니까?

내부 개인 메서드, 필드 또는 중첩 클래스가있는 클래스를 단위 테스트 (xUnit 사용)하려면 어떻게합니까? 또는 내부 연결 ( staticC / C ++에서)을 사용하여 개인용으로 만들거나 개인용 ( 익명 ) 네임 스페이스에 있는 함수 입니까?

테스트를 실행할 수 있도록 메소드 또는 함수에 대한 액세스 수정자를 변경하는 것은 좋지 않습니다.



답변

최신 정보:

약 10 년 후 아마도 개인 방법 또는 접근 할 수없는 멤버를 테스트하는 가장 좋은 방법 @Jailbreak매니 폴드 프레임 워크 를 이용하는 것 입니다.

@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;

이런 식으로 코드를 안전하게 입력하고 읽을 수 있습니다. 테스트를위한 디자인 타협, 과도한 노출 방법 및 필드가 없습니다.

레거시 Java 애플리케이션이 있고 메소드의 가시성을 변경할 수없는 경우 개인 메소드를 테스트하는 가장 좋은 방법은 reflection 을 사용하는 입니다.

내부적으로 우리는 헬퍼를 사용하여 get / set privateprivate static변수뿐만 아니라 호출 privateprivate static메소드를 사용합니다. 다음 패턴을 사용하면 개인 메소드 및 필드와 관련된 거의 모든 작업을 수행 할 수 있습니다. 물론 private static final리플렉션을 통해 변수를 변경할 수는 없습니다 .

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

그리고 필드의 경우 :

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

참고 :
1. 메소드 TargetClass.getDeclaredMethod(methodName, argClasses)를 살펴볼 수 있습니다 private. 같은 것이 적용됩니다
getDeclaredField.
2. 개인 setAccessible(true)과 놀아야합니다.


답변

비공개 메소드를 테스트하는 가장 좋은 방법은 다른 공개 메소드를 사용하는 것입니다. 이를 수행 할 수없는 경우 다음 조건 중 하나에 해당합니다.

  1. 전용 메소드는 데드 코드입니다
  2. 테스트중인 클래스 근처에 디자인 냄새가 있습니다.
  3. 테스트하려는 방법은 비공개가 아니어야합니다

답변

개인 메서드를 직접 테스트해야 할 정도로 충분히 복잡한 클래스에 개인 메서드가 있으면 코드 냄새가납니다. 클래스가 너무 복잡합니다.

이러한 문제를 해결하기위한 나의 일반적인 접근 방식은 흥미로운 부분을 포함하는 새로운 클래스를 만드는 것입니다. 종종,이 방법과 상호 작용하는 필드, 아마도 다른 방법 또는 두 개를 새로운 클래스로 추출 할 수 있습니다.

새 클래스는 이러한 메소드를 ‘공개’로 노출하므로 단위 테스트에 액세스 할 수 있습니다. 새 클래스와 기존 클래스는 이제 원래 클래스보다 간단합니다. 이는 간단합니다 (물건을 단순하게 유지해야하거나 길을 잃을 수 있습니다!).

사람들이 자신의 두뇌를 사용하지 않고 수업을 만들 것을 제안하지는 않습니다. 여기서 중요한 점은 좋은 새로운 수업을 찾는 데 도움이되는 단위 테스트의 힘을 사용하는 것입니다.


답변

과거에 Java에 대해이 작업을 수행하기 위해 리플렉션 을 사용 했으며 내 의견으로는 큰 실수였습니다.

엄밀히 말하면 개인 메소드를 직접 테스트하는 단위 테스트를 작성 해서는 안됩니다 . 당신이 해야 테스트 할 것은 클래스가 다른 객체와 함께 가지고있는 공공 계약이다; 객체의 내부를 직접 테스트해서는 안됩니다. 다른 개발자가 클래스의 내부 계약에 영향을 미치지 않는 클래스의 작은 내부 변경을 원할 경우 리플렉션 기반 테스트를 수정하여 작동하는지 확인해야합니다. 프로젝트 전체에서이 작업을 반복적으로 수행하면 단위 테스트가 코드 상태의 유용한 측정을 중단하고 개발에 방해가되고 개발 팀에 성가심이되기 시작합니다.

대신 내가 권장하는 것은 Cobertura와 같은 코드 범위 도구를 사용하여 작성하는 단위 테스트가 개인 방법으로 코드의 적절한 범위를 제공하는지 확인하는 것입니다. 이렇게하면 개인 방법이 수행하는 작업을 간접적으로 테스트하고 더 높은 민첩성을 유지할 수 있습니다.


답변

이 기사 : JUnit 및 SuiteRunner (빌 벤너)를 사용 하여 개인 메소드 테스트 에는 기본적으로 4 가지 옵션이 있습니다.

  1. 개인용 메소드를 테스트하지 마십시오.
  2. 메소드 패키지 액세스를 제공하십시오.
  3. 중첩 된 테스트 클래스를 사용하십시오.
  4. 반사를 사용하십시오.

답변

일반적으로 단위 테스트는 클래스 또는 단위의 공용 인터페이스를 연습하기위한 것입니다. 따라서 전용 메소드는 명시 적으로 테스트하지 않을 구현 세부 사항입니다.


답변

개인 메소드를 테스트하려는 위치의 두 가지 예 :

  1. 해독 루틴 -테스트 목적으로 만 볼 수 있도록 다른 사람이 볼 수 있도록하고 싶지 않으면 다른 사람이 해독을 위해 사용할 수 있습니다. 그러나 그것들은 코드에 내재되어 있고 복잡하며 항상 작동해야합니다 (명확한 예외는 SecurityManager이것을 막도록 구성되지 않은 경우 대부분의 경우 개인 메소드조차도 볼 수있는 반영입니다 ).
  2. 커뮤니티 소비를 위한 SDK 작성 여기에서 대중은 완전히 다른 의미를 취합니다. 전 세계가 볼 수있는 코드이기 때문에 (내 응용 프로그램의 내부가 아니라). SDK 사용자가 그것을보고 싶지 않으면 코드를 개인 메소드에 넣습니다. SDK 프로그래밍이 작동하는 방식으로 코드 냄새로 보지 않습니다. 그러나 물론 여전히 개인 메서드를 테스트해야하며 SDK의 기능이 실제로 존재하는 곳입니다.

“계약”만 테스트한다는 생각을 이해합니다. 그러나 실제로 코드를 테스트하지 말라고 주장 할 수는 없습니다. 마일리지는 다를 수 있습니다.

그래서 내 장단점은 보안 및 SDK를 손상시키지 않고 JUnit을 반영하여 복잡하게 만드는 것입니다.