2011-08-16 7 views
7

개인 방법 테스트의 의미에 대해 다른 의견이 있습니다 (예 : herehere). 나는 개인적으로 그것이 합리적이라고 생각한다. 문제는 그것을 올바르게하는 것이다. C++에서 #define hack을 사용하거나 테스트 클래스 friend을 만들 수 있습니다. C#에는 InternalsVisibleToAttribute이 있지만 Java에서는 reflection을 사용하거나 의도를 명확하게하기 위해 테스트 용으로 표시 가능하도록 annotate them as such을 사용해야합니다. 둘 다의 단점은 분명해야합니다.개인 도구 테스트 용 Java 도구?

나는 더 나은 것이 있어야한다고 생각합니다. 그것은 좋은 것

public class Something { 
    private int internalSecret() { 
     return 43; 
    } 
} 

시작하면 주석이 자동 반사를 사용하여 something의 개인 방법으로 모든 통화를 변환 할 다음

@MakeVisibleForTesting Something something = new Something(); 
Assert.assertEquals(43, something.internalSecret()); 

같은 테스트 코드에서 private 메소드를 호출 할 수 있습니다. 나는 Lombok가 그것을 할 수 있는지 궁금하다 (그리고 저자에게 물을 것이다).

많은 마법을 사용하는 것이 너무 복잡하고 어떤 경우에는 시간이 걸릴 수 있으므로 가능한 대안을 찾고 있습니다. 어쩌면 @Decapsulate 같은과 테스트중인 클래스를 주석과

Decapsulated_Something something = new Decapsulated_Something(new Something()); 
Assert.assertEquals(43, something.internalSecret()); 

를 사용할 수 있도록 할

public class Decapsulated_Something { 
    public Decapsulated_Something(Something delegate) { 
     this.delegate = delegate 
    } 
    public boolean internalSecret() { 
     // call "delegate.internalSecret()" using reflection 
    } 
    ... 
} 

처럼 보이는 클래스 Decapsulated_Something를 생성하는 주석 프로세서를 사용하여 나는 주석과 많은 경험이없는 처리하기 때문에 여기에서 먼저 묻습니다 :

  • 구현이 얼마나 복잡합니까?
  • 무엇을 잊었습니까?
  • 일반적으로 어떻게 생각하십니까?
+0

전나무에게 도구를 요청하거나 직접 작성하는 방법이 있습니까? – Raedwald

+0

@Raedwald 나는 그것을 해결하는 방법을 묻습니다. 자신을 짜내는 것이 하나의 옵션이지만, 바퀴를 다시 발명하는 것은 명백하게 요구되지 않습니다. – maaartinus

답변

1

이 방법 주석과 같은 것이있다

@MakeVisibleForTesting Something something = new Something(); 
Assert.assertEquals(43, something.internalSecret()); 

같은 테스트 코드에서 개인 메서드를 호출 할 수있는 것이 좋을 것이다, 체크 아웃 dp4j@TestPrivates :

@Test 
@TestPrivates 
//since the method is annotated with JUnit's @Test this annotation is redundant. 
// You just need to have dp4j on the classpath. 
    public void somethingTest(){ 
     Something something = new Something(); 
     int sthSecret = something.internalSecret(); 
     Assert.assertEquals(43, sthSecret); //cannot use something.internalSecret() directly because of bug [dp4j-13][2] 
    } 
7

이 구현을 수행하는 데 많은 어려움이있는 것처럼 보입니다. 그럴만한 가치가 없을 수도 있습니다. 대신 메서드 패키지를 기본값으로 설정합니다.

그러나 개인 메서드를 호출하기로 결정한 경우 Decapsulated_something 클래스의 setAccessible을 사용하여 리플렉션을 통해 호출을 허용 할 수 있습니다. 그래서 매우 간단합니다.

+0

+1 개인용 패키지. – Thilo

1

"일반적으로"질문에 답변 해 드리겠습니다 :-) 리플렉션을 통해 메소드에 액세스 할 수 있도록 코드를 몇 줄만 입력하면 꽤 많은 라이브러리, 유틸리티, API 등을 통해 메소드 수행 방법을 제공합니다. 그래서. 또한 자신의 코드에서 사용할 수있는 여러 가지 기술이있을 수 있습니다. 예를 들어, 바이트 코드 조작, 반사, 클래스 확장 등.하지만 일을 단순하게 유지하려고합니다. 개인적인 방법을 테스트하는 것이 유용 할 수 있지만, 몇 가지를 테스트하기를 원할 수도 있습니다. 그래서 복잡한 것을 엔지니어링하는 것은 아마도 과잉입니다. 나는 단지 설립 된 API를 사용하거나, 관심이있는 개인적인 방법에 접근 할 수있는 빠른 방법을 작성하고, 그렇게 할 수 있도록했다.

1

는 방법의 수들이 호출자에게 변화를해서는 안 구현 세부 사항 숨겨진으로

  • 개인 방법을 테스트하지 마십시오 취할 수 있습니다.
  • 호출자가 패키지에 액세스 할 수 없도록 패키지를 로컬로 설정하지만 동일한 패키지, 즉 유닛 테스트에 액세스 할 수 있습니다.
  • 유닛 테스트를 내부 클래스로 만들거나 패키지 로컬 내부 클래스를 제공하십시오. 이것이 개선인지 확실하지 않습니다!
  • 리플렉션을 사용하여 클래스의 메서드에 액세스합니다. 이것은 메소드 rpivate를 표시하지 않는 것과 같고 혼동 IMHO입니다. 개인적으로 비공개 인 경우 메소드를 비공개로 표시해야합니다.
1

나는 단위 테스트 개인 메서드를 쉽게 만들기 위해 클래스를 생성 한 몇 년 전에 프로젝트에서 일했습니다. http://java.net/projects/privateer/

리플렉션을 호출하는 것보다 손쉽게 만들 수있는 추가 클래스가 생성되었습니다. MyClass.myPrivateMethod()가 있으면 myPrivateMethod를 직접 호출 할 수있는 _MyClass 클래스를 생성합니다.

정말 끝내지 않았으며 몇 가지 경우에는 유용했지만 전반적으로 절대적으로 필요한 경우가 아니면 개인적인 방법을 테스트하지 않는 것이 좋습니다. 일반적으로 패키지를 사용하는 사용자가 걱정된다면 유틸리티 클래스로 다시 디자인하는 것이 더 좋습니다.