programing tip

테스트 클래스에 대해서만 비공개 메서드를 공개하는 주석

itbloger 2020. 10. 5. 07:42
반응형

테스트 클래스에 대해서만 비공개 메서드를 공개하는 주석 [중복]


공통된 필요에 대한 해결책을 가진 사람.

내 응용 프로그램에 수업이 있습니다.

일부 메서드는 api의 일부이기 때문에 공용이고 일부는 내부 흐름을 더 읽기 쉽게 만들기위한 내부 사용을위한 개인용입니다.

이제 단위 테스트를 작성하거나 통합 테스트와 비슷합니다. 다른 패키지에 위치하여이 메서드를 호출 할 수 있지만이 메서드에 대한 정상적인 호출이 허용되지 않기를 바랍니다. 응용 프로그램 자체의 클래스에서 호출하려고하면

그래서 그런 생각을 했어요

public class MyClass {

   public void somePublicMethod() {
    ....
   }

   @PublicForTests
   private void somePrivateMethod() {
    ....
   }
}

위의 주석은 private 메서드를 "public for tests"로 표시합니다. 즉, 컴파일 및 런타임은 test ... package 아래에있는 모든 클래스에 대해 허용되지만 컴파일 및 / 또는 런타임은 다음 클래스에 대해 실패합니다. 테스트 패키지 아래가 아닙니다.

이견있는 사람? 이와 같은 주석이 있습니까? 이 작업을 수행하는 더 좋은 방법이 있습니까?

더 많은 단위 테스트를 작성할수록 캡슐화가 더 많이 강화되는 것 같습니다 ...


일반적인 방법은 private 메서드를 protected 또는 package-private로 만들고이 메서드에 대한 단위 테스트를 테스트중인 클래스와 동일한 패키지에 넣는 것입니다. Guava에는 @VisibleForTesting주석 이 있지만 문서화 목적으로 만 사용됩니다.


테스트 범위가 테스트 된 클래스 내의 모든 공용 메서드에 대해 좋은 경우 가능한 모든 경우를 주장하므로 공용 메서드에서 호출 한 privates 메서드가 자동으로 테스트됩니다.

JUnit Doc은 다음과 같이 말합니다.

private 메서드를 테스트하는 것은 재사용 가능성을 높이기 위해 해당 메서드를 다른 클래스로 이동해야한다는 표시 일 수 있습니다. 하지만 필요한 경우 ... JDK 1.3 이상을 사용하는 경우 리플렉션을 사용하여 PrivilegedAccessor의 도움으로 액세스 제어 메커니즘을 파괴 할 수 있습니다. 사용 방법에 대한 자세한 내용은 이 기사를 참조하십시오.


인터페이스를 사용하여 API 메서드를 노출하고, 팩토리 또는 DI를 사용하여 개체를 게시하여 소비자가 인터페이스를 통해서만 알 수 있도록하십시오. 인터페이스는 게시 된 API를 설명합니다. 이렇게하면 구현 개체에서 원하는 것을 공개 할 수 있으며 해당 개체의 소비자는 인터페이스를 통해 노출 된 메서드 만 볼 수 있습니다.


dp4j 에는 필요한 것이 있습니다. 기본적으로 클래스 경로에 dp4j를 추가하기 만하면됩니다. @Test (JUnit의 주석)로 주석 처리 된 메서드가 비공개 메서드를 호출 할 때마다 작동합니다 (dp4j는 컴파일 타임에 필요한 리플렉션을 삽입합니다). dp4j의 @TestPrivates 주석을 사용하여 더 명확하게 표현할 수도 있습니다.

비공개 메소드에 주석을 추가해야한다고 주장하는 경우 Google의 @VisibleForTesting 주석을 사용할 수 있습니다.


비공개 메서드 테스트 에 대한 기사는 비공개 코드를 테스트하는 몇 가지 접근 방식을 설명합니다. 리플렉션을 사용하면 프로그래머가 리팩토링이 완료되면 문자열이 자동으로 변경되지 않는지 기억해야하는 부담이 더해 지지만 가장 깔끔한 접근 방식이라고 생각합니다.


또는이 방법을 일부 전략 개체 로 추출 할 수 있습니다 . 이 경우 추출 된 클래스를 쉽게 테스트 할 수 있으며 리플렉션 / 바이트 코드를 사용하여 메서드를 공개하거나 마법을 사용하지 마십시오.


나는 그러한 주석에 대해 알지 못하지만 다음 은 가치가있을 수 있습니다 : 단위 테스트 개인 메서드
또는 다음 : JMockit


당신은 이것을 할 수 없습니다. 그러면 어떻게 당신의 테스트를 컴파일 할 수 있습니까? 컴파일러는 주석을 고려하지 않습니다.

이에 대한 두 가지 일반적인 접근 방식이 있습니다.

첫 번째는 리플렉션을 사용하여 메서드에 액세스하는 것입니다.

두 번째는 private 대신 package-private를 사용하고 동일한 패키지 (그러나 다른 모듈)에 테스트를 포함하는 것입니다. 기본적으로 다른 코드에 대해 비공개이지만 테스트는 계속 액세스 할 수 있습니다.

물론, 블랙 박스 테스트를 수행하는 경우 어쨌든 비공개 멤버에 액세스해서는 안됩니다.


최근 리플렉션을 통해 private 필드, 메서드 및 내부 클래스에 액세스하는 데 많은 도움이되는 라이브러리를 출시했습니다. BoundBox

같은 수업

public class Outer {
    private static class Inner {
        private int foo() {return 2;}
    }
}

다음과 같은 구문을 제공합니다.

Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();

당신이 BoundBox 클래스를 생성해야 할 유일한 것은 작성하는 것입니다 @BoundBox(boundClass=Outer.class)그리고 BoundBoxOfOuter클래스는 즉시 생성됩니다.


Okay, so here we have two things that are being mixed. First thing, is when you need to mark something to be used only on test, which I agree with @JB Nizet, using the guava annotation would be good.

A different thing, is to test private methods. Why should you test private methods from the outside? I mean.. You should be able to test the object by their public methods, and at the end that its behavior. At least, that we are doing and trying to teach to junior developers, that always try to test private methods (as a good practice).


As much as I know there is no annotation like this. The best way is to use reflection as some of the others suggested. Look at this post:
How do I test a class that has private methods, fields or inner classes?

You should only watch out on testing the exception outcome of the method. For example: if u expect an IllegalArgumentException, but instead you'll get "null" (Class:java.lang.reflect.InvocationTargetException).
A colegue of mine proposed using the powermock framework for these situations, but I haven't tested it yet, so no idea what exactly it can do. Although I have used the Mockito framework that it is based upon and thats a good framework too (but I think doesn't solve the private method exception issue).

It's a great idea though having the @PublicForTests annotation.

Cheers!


I just put the test in the class itself by making it an inner class: http://www.ninthavenue.com.au/how-to-unit-test-private-methods

참고URL : https://stackoverflow.com/questions/6913325/annotation-to-make-a-private-method-public-only-for-test-classes

반응형