Maven을 사용하여 사용자 정의 클래스 로더를 테스트하기위한 별도의 JAR 파일을 구축합니다.

StackOverflow https://stackoverflow.com/questions/1401857

문제

현재 프로젝트의 일환으로 커스텀 클래스 로더를 만들었습니다. 사용자 정의 로더의 장치 테스트의 일부는 일부 JAR 파일을 사용하여 로더의 적절한 동작을 보여주는 것입니다.

실제 단위 테스트를 실행하기 전에 Java 소스에서 테스트 JAR 파일을 구축하고 싶습니다. 또한 테스트 실행 중에 동적으로로드하려면 장치 테스트를 실행할 때 테스트 JAR 파일이 클래스 경로에있을 수 없습니다.

이런 종류의 "테스트 단계 전에 옆에 항아리를 구축하지만 클래스 경로에서 벗어나게한다"요구 사항을 달성하기위한 표준 패턴이 있습니까? 나는 Maven 2와 함께 이것을 시도한 첫 번째 사람이라고 믿을 수 없지만 올바른 POM 구조와 종속성에 맞지 않는 것 같습니다. 일반적으로 테스트 단계에 앞서 구축되지 않은 일부 테스트 병으로 끝나지만 일관되지 않은 건축 순서에도 문제가 있었는데 한 머신에서 빌드가 제대로 작동하지만 일부는 빌드하지 못합니다. 다른 항아리를 테스트하십시오.

도움이 되었습니까?

해결책

가장 간단한 일은 테스트 용기의 클래스를 포장하기위한 다른 프로젝트를 설정 한 다음이를 정상으로 설정하는 것입니다. 테스트 스코핑 의존.

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

어셈블리 플러그인은 대상/테스트 클래스의 내용을 포장하는 어셈블리 디스크립터 (src/main/어셈블리, test-assembly.xml이라고 함)를 사용합니다. com.test 패키지와 그 어린이의 내용을 포함하도록 필터를 설정했습니다. 이것은 항아리의 내용을 신청할 수있는 패키지 이름 컨벤션이 있다고 가정합니다.

어셈블리 플러그인은 기본적으로 항아리를 지정하여 추가 아티팩트로 첨부합니다. attach 거짓으로 설치/배포되지 않습니다.

<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>

이것은 test-assembly.xml의 내용입니다

<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>

다른 팁

테스트 내에서 테스트에 필요한 모든 것을 설정하려고 노력할 것입니다. 주요 장점은 테스트에 암시적인 마법의 보이지 않는 설정이 없다는 것입니다. 테스트는 모든 환경에서 실행될 수 있습니다. 또한 일부 혼합 시나리오 설정에 의존하지 않기 때문에 엄격하게 격리 된 새로운 시나리오를 추가하는 것이 훨씬 쉽습니다.

설정이 너무 어렵지 않아야합니다.

  • Java 클래스 직렬화 :
    • 일부 유형 코드 엔지니어링 라이브러리
    • 또는 .class 이외의 일부 파일 접미사로 이름이 바뀌는 Java 클래스 파일을 사용하십시오. 테스트 자원 폴더 아래에 넣고 클래스 로더 (getResourceasstream (...))로로드하십시오.
  • 클래스 파일을 지퍼 (`java.util.zip.gzipoutputstream`)
  • 클래스 로더로 클래스 파일을로드하십시오

Java 클래스 로더 디자인을 사용하고 추가 클래스를 생성하지 않고 작동하는 대체 접근 방식이 있습니다.

Java에는 클래스 로더 계층 구조가 있습니다. 모든 클래스 로더에는 부모 클래스 로더가 있습니다. 클래스 로더 계층의 루트는 부트 클래스 로더입니다. 클래스에 클래스 로더가로드되면 부모 클래스 로더와 함께 클래스를 먼저로드하려고합니다.

현재 클래스 로더로 테스트 클래스를로드 할 수 있습니다. 그것을 용기하고 자신의 클래스 로더로로드하십시오. 유일한 차이점은 부모 클래스 로더를 테스트 클래스로드 할 수없는 로더로 설정한다는 것입니다.

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();

Maven은 종속성 분석을 통해 빌드 순서를 해결하므로 일반적으로 항아리가 순서대로 구축됩니다. 테스트 항아리를 사용하는 것이 단순히 종속성으로 선언하기 때문입니다. 그러나 종속성도 클래스 경로에 배치됩니다. 종속성의 "범위"는 어떤 클래스 경로가 진행되는지 결정합니다. 예를 들어 '컴파일'종속성은 컴파일, 테스트 및 실행을위한 클래스 경로에 있습니다. '런타임'종속성은 테스트 및 실행을위한 클래스 경로에 있습니다. '테스트'종속성은 테스트 중에 클래스 경로에만 있습니다. 불행히도, 당신은 사용 가능한 범위에 의해 다루지 않는 경우가 있습니다. 당신은 종속성이 있지만 클래스 경로에서는 그것을 원하지 않습니다. 이것은 프린지 사용 사례이며 사례를 발견하는 데 어려움이있는 이유입니다.

따라서 일부 Maven Guru가 그 반대를 나타 내기 위해 뒤를 잇지 않는 한, 특별한 Maven 플러그인을 쓰지 않고는 이것이 불가능하다고 제안합니다. 그러나 그 대신에 다른 것을 추천합니다. 클래스 로더를 테스트하기 위해 맞춤형 항아리가 정말로 필요합니까? 그것은 나에게 비린내 들린다. 아마도 오래된 병을 사용할 수 있습니까? 그렇다면 Maven-Dependency-Plugin을 사용하여 항상 저장소에있는 것으로 알려진 JAR (예 : LOG4J)을 로컬 모듈의 대상 디렉토리에 복사합니다. 그런 다음 테스트는 FilePath를 통해 해당 항아리에 액세스 할 수 있습니다. target/log4j-xxx.jar 그리고 당신은 당신의 일을 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top