2009-09-09 2 views
3

현재 프로젝트의 일부로 사용자 정의 클래스 로더를 작성했습니다. 커스텀 로더의 단위 테스트의 일부는, JAR 파일을 사용해, 로더의 적절한 동작을 나타냅니다.Maven을 사용하여 단위 테스트 용 개별 JAR 파일 작성하기

실제 단위 테스트를 실행하기 전에 Java 소스에서 테스트 JAR 파일을 빌드하고 싶습니다. 또한, 테스트 JAR 파일은 유닛 테스트가 실행될 때 클래스 경로에있을 수 없습니다. 테스트 실행 중에 동적으로로드하려고하기 때문입니다.

"테스트 단계 이전에 일부 JAR을 빌드했지만 클래스 경로를 벗어나게"하는 이런 종류의 작업을 수행하기위한 표준 패턴이 있습니까? Maven 2에서이 작업을 처음 시도한 사람이라고는 믿을 수 없지만 올바른 POM 구조와 종속성에 맞지 않는 것처럼 보입니다. 보통 테스트 단계 이전에 빌드되지 않은 일부 테스트 jar로 끝나지 만 빌드 순서가 일관되지 않아 빌드가 한 시스템에서 제대로 작동하지 못하고 일부 빌드를 빌드하지 못했습니다. 다른 항아리를 테스트하십시오.

+0

확실하지 테스트 assembly.xml의 내용이다. 테스트를 실행하기 전에 특정 테스트 클래스에서 항아리를 만들고 싶습니까? –

+0

테스트가 정확히 단위 테스트가 아닙니다. 고립 된 유닛을 테스트하는 것이 아니라 여러 유닛 (클래스 로더, 자바 클래스 로더, 파일 io)의 통합을 테스트합니다. –

+0

테스트 및 통합 테스트를 추가하여 더 많은 응답을 얻을 수 있습니다. –

답변

5

가장 간단한 방법은 테스트 용기의 클래스를 패키징하도록 다른 프로젝트를 설정 한 다음 해당 프로젝트를 보통 test-scoped 종속성으로 설정하는 것입니다.

원하지 않거나 할 수없는 경우 어셈블리 플러그인을 사용하여 process-test-classes 단계 (즉, 테스트가 컴파일 된 후 테스트가 실행되기 전에)에 jar 파일을 만들 수 있습니다. 아래의 구성은 어셈블리 디렉토리를 호출하여 대상 디렉토리에서 해당 단계의 classloader-test-deps이라는 jar 파일을 만듭니다. 그러면 테스트에서 필요에 따라 해당 항아리를 사용할 수 있습니다.

어셈블리 플러그인은 target/test-classes의 내용을 패키징하는 어셈블리 설명자 (src/main/assembly에서 test-assembly.xml)를 사용합니다. 나는 com.test 패키지와 그 자식의 내용을 포함하도록 필터를 설정했다. 이것은 jar의 내용을 적용 할 수있는 패키지 이름 규칙을 가지고 있다고 가정합니다.

어셈블리 플러그인은 기본값으로 attach을 false로 지정하여 추가 아티팩트로 jar를 첨부합니다. 설치 및 배포되지 않습니다.

<plugin> 
    <artifactId>maven-assembly-plugin</artifactId> 
    <version>2.2-beta-2</version> 
    <executions> 
    <execution> 
     <id>create-test-dependency</id> 
     <phase>process-test-classes</phase> 
     <goals> 
     <goal>single</goal> 
     </goals> 
     <configuration> 
     <finalName>classloader-test-deps</finalName> 
     <attach>false</attach> 
     <descriptors> 
      <descriptor>src/main/assembly/test-assembly.xml</descriptor> 
     </descriptors> 
     </configuration> 
    </execution> 
    </executions> 
</plugin> 

내가 질문을 이해

<assembly> 
    <id>test-classloader</id> 
    <formats> 
    <format>jar</format> 
    </formats> 
    <includeBaseDirectory>false</includeBaseDirectory> 
    <fileSets> 
    <fileSet> 
     <directory>${project.build.testOutputDirectory}</directory> 
     <outputDirectory>/</outputDirectory> 
     <!--modify/add include to match your package(s) --> 
     <includes> 
     <include>com/test/**</include> 
     </includes> 
    </fileSet> 
    </fileSets> 
</assembly> 
+0

적절한 종속성은 실제로 테스트 범위입니다. 제안한 어셈블리 플러그인 방식이 좋습니다. 나는 그것에게 소용돌이를 줄 것이다! – rtenhove

+0

리치 셀러 :이 두 가지 답변이 모두 올바른 것으로 나타났습니다. 내 자신의 어리 석음 때문에 테스트 용기 생성을 위해 POM을 미묘하게 깨뜨릴 수있었습니다. 일단 고정되면, 테스트 스코핑은 예상대로 작동했지만, 메이븐 (Maven) 단서를 통해 나에게 매우 어려운 문제를 만들었다. 나는 또한 어셈블리 플러그인을 사용해 보았지만 잘 작동했다. 유연성은보다 복잡한 상황에서 매우 유용 할 수 있습니다. – rtenhove

5

테스트 중에 필요한 모든 테스트를 설정하려고합니다. 가장 큰 장점은 테스트에 암묵적인 마술 보이지 않는 설정이 없다는 것입니다. 이 테스트는 모든 환경에서 실행할 수 있습니다. 또한 일부 시나리오가 혼합 된 경우에 의존하지 않으므로 엄격하게 격리 된 새 시나리오를 추가하는 것이 훨씬 쉽습니다.

셋업 너무 열심히 안 :

  • 직렬화 자바 클래스 : 어떤 종류의 코드 엔지니어링 라이브러리
    • 또는 이외의 파일 확장자로 이름이 변경 자바 클래스 파일을 사용합니다. 수업. 테스트 리소스 폴더 아래에 놓고 클래스 로더 (getResourceAsStream (...))로로드하십시오.
  • 는 클래스 로더와 클래스 파일 (`java.util.zip.GZIPOutputStream`)
  • 부하 클래스 zip 파일을

자바 클래스 로더 설계를 사용하는 또 다른 방법이있다 추가 수업이 없어도 효과가 있습니다.

자바 클래스 로더 계층 구조가 있습니다. 모든 클래스 로더에는 부모 클래스 로더가 있습니다. 클래스 로더 계층 구조의 루트는 부트 클래스 로더입니다. 클래스 로더가로드 될 때, 클래스 로더를 먼저로드하고 그 다음에 클래스 로더를로드하려고 시도합니다.

현재 클래스 로더로 테스트 클래스를로드 할 수 있습니다. Jar로 자신의 클래스 로더로로드하십시오. 유일한 차이점은 테스트 클래스를로드 할 수없는 상위 클래스 로더를 설정한다는 것입니다.

String resource = My.class.getName().replace(".", "/") + ".class"; 

//class loader of your test class 
ClassLoader myClassLoader = currentThread().getContextClassLoader(); 
assert ! toList(myClassLoader.getResources(resource)).isEmpty(); 

//just to be sure that the resource cannot be loaded from the parent classloader 
ClassLoader parentClassloader = getSystemClassLoader().getParent(); 
assert toList(parentClassloader.getResources(resource)).isEmpty(); 

//your class loader 
URLClassLoader myLoader = new URLClassLoader(new URL[0], parentClassloader); 
assert toList(myLoader.getResources(resource)).isEmpty(); 
+0

답변을 제공했지만 문제의 제약 조건을 완화 할 수 있다면이 방법을 선호합니다. – SingleShot

+0

원하는 경우 JarOutputStream을 사용하여 GZIPOutputStream 클래스를 확장하여 jar 파일을 만들 수도 있습니다. – aperkins

+0

differnce는 무엇입니까? 명시 적 지원? –

0

은 Maven은 테스트 JAR 파일을 사용하는 사람이 단순히 종속 관계로 선언 때문에 그래서 일반적으로 당신의 항아리 위해 구축 것, 의존성 분석을 통해 순서를 구축 해결합니다. 그러나 클래스 경로에도 종속성이 있습니다. 의존성의 "범위"는 어떤 클래스 패스가 계속 진행될 것인지 결정합니다. 예를 들어 'compile'의존성은 컴파일, 테스트 및 실행을위한 클래스 경로에 있습니다. '런타임'종속성은 테스트 및 실행을위한 클래스 경로에 있습니다. 'test'종속성은 테스트 중에 classpath에만 있습니다. 안타깝게도 사용 가능한 범위에 포함되지 않은 케이스가 있습니다. 의존성이 있지만 classpath에는 필요하지 않습니다. 이것은 프린지 사용 사례이므로 예제를 찾는 데 어려움을 겪고있는 것입니다.

따라서 일부 Maven 전문가가 그 반대를 나타 내기 전까지는 특별한 Maven 플러그인을 작성하지 않으면 불가능하다고 생각합니다. 그러나 그 대신에 저는 다른 것을 권합니다. 클래스 로더를 테스트하기 위해 맞춤형 JAR이 정말로 필요합니까? 그게 나 한테 비린내 같아. 아마도 이전 JAR을 사용할 수 있습니까? 그렇다면 maven-dependency-plugin을 사용하여 항상 저장소 (예 : log4j)에있는 JAR을 로컬 모듈의 대상 디렉토리에 복사합니다. 그러면 테스트는 파일 경로를 통해 target/log4j-xxx.jar에있는 JAR에 액세스 할 수 있으며 작업을 수행 할 수 있습니다.

+0

정말 특별한 항아리가 필요합니다. 이 테스트는 구현중인 플러그인 아키텍처의 특정 패턴에 대한 지원을 표시하기위한 것입니다 (OSGi와 같은 경우에는 너무 간단 함). "표준"항아리는이 패턴에 맞지 않습니다, AFAIK. – rtenhove

관련 문제