Usando Maven para construir arquivos JAR separados para unidade testar um carregador de classe personalizada

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

Pergunta

Como parte do meu projeto atual eu criei um carregador de classe personalizado. Parte dos testes de unidade para o carregador de costume envolve o uso de alguns arquivos JAR para demonstrar o comportamento adequado do carregador.

Eu gostaria de construir os arquivos JAR de teste a partir de fontes Java antes de executar os testes de unidade real. Além disso, os arquivos jar test não pode estar no caminho de classe quando os testes de unidade são executados, desde que eu quero carregá-los dinamicamente durante a execução do teste.

Existe um padrão padrão para realizar este tipo de "construir alguns JARs no lado antes da fase de teste, mas deixá-los fora do caminho de classe" exigência? Eu não posso acreditar que eu sou a primeira pessoa a tentar fazer isso com Maven 2, mas eu não consigo bater na estrutura POM direita e dependências. Normalmente eu acabar com alguns dos frascos de teste não sendo construídos à frente da fase de teste, mas eu também tive problemas com inconsistente fim-de-build causando a criação funcionar corretamente em uma máquina, mas não conseguem construir algumas das frascos de teste em outro.

Foi útil?

Solução

A coisa mais simples a fazer é configurar outro projeto para empacotar as classes para o seu jar test, em seguida, defina-o como um normal, teste de escopo dependência.

Se você não quer / não são capazes de fazer isso, você pode usar o conjunto de plugins para criar um frasco na fase process-test-classes (ou seja, após os testes foram compilados, mas antes dos testes são executados). A configuração abaixo irá invocar o conjunto de encaixe para criar um frasco chamado classloader-test-deps em que fase no directório alvo. Os testes podem então usar esse frasco, conforme necessário.

Os usos montagem plugins um descritor de montagem (em src / main / montagem, chamado test-assembly.xml) que empacota o conteúdo de / test-classes alvo. Eu configurar um filtro para incluir o conteúdo do pacote com.test e seus filhos. Isso pressupõe que você tem alguma convenção nome do pacote que você pode aplicar para o conteúdo do frasco.

A vontade de montagem de encaixe por padrão anexar o jar como um artefato adicionais, especificando attach como falsa, não serão instalados / implantado.

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

Este é o conteúdo de 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>

Outras dicas

Gostaria de tentar configurar tudo seus testes precisa de dentro do teste. A principal vantagem é que não há nenhuma configuração invisível mágica que está implícita para o teste. O teste pode ser executado em todos os ambientes. Além disso, é muito mais fácil adicionar novos cenários estritamente isolados como você não está dependente de alguma configuração cenário misto.

A instalação não deve ser muito difícil:

  • serializar uma classe java:
    • com alguma biblioteca tipo engenharia de código
    • Como alternativa, use um arquivo de classe java renomeado para alguns sufixo arquivo diferente de .class. Colocá-lo na pasta de recursos de teste e de carga com o carregador de classe (getResourceAsStream (...)).
  • zip o arquivo de classe ( `java.util.zip.GZIPOutputStream`)
  • carregar o arquivo de classe com a classe loader

Existe uma abordagem alternativa que usa o design carregador de classe java e funciona sem geração de classes adicionais.

Java tem uma hierarquia carregador de classe. Cada carregador de classe tem um carregador de classe pai. A raiz da hierarquia do carregador de classes é o carregador de classe de inicialização. Quando uma classe é carregada com um carregador de classe ele vai tentar carregar a classe em primeiro lugar com o carregador de classe pai e depois em si.

Você pode carregar a classe de teste com o carregador de classe atual. Jar-lo e carregá-lo com seu próprio carregador de classe. A única diferença é que você definir o carregador de classe pai para um que não pode carregar sua classe de teste.

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 resolve ordem de construção através de análise de dependência, assim normalmente seus JARs iria construir em ordem, porque aquele que usa seus frascos de teste seria simplesmente declará-los como dependências. No entanto, dependências também são colocados no caminho de classe. O "escopo" de uma dependência determina qual classpath vai. Por exemplo 'compilação' dependências estão no caminho da classe para compilar, testar, e em execução; 'Execução' dependências estão no caminho de classe para testar e execução; 'Teste' dependências são apenas sobre o caminho de classe durante o teste. Infelizmente, você tem um caso não abrangidos por qualquer um dos escopos disponíveis: você tem uma dependência, mas você não quer que ele no classpath. Este é um caso de uso franja e é por isso que você está tendo problemas para descobrir exemplos.

Assim, a menos que algum guru Maven eleva-se para indicar o contrário, eu sugiro que isso é impossível sem escrever um plugin especial Maven. Em vez disso, no entanto, eu recomendo algo mais. Você realmente precisa de JARs custom-built para testar o seu carregador de classe? Isso parece suspeito para mim. Talvez você pode usar qualquer JAR velho? Se assim for, gostaria de usar o maven-dependência do plugin para copiar alguns JAR conhecido por estar sempre em seu repositório (log4j por exemplo) no diretório de destino do seu módulo local. Seu teste pode, então, acesso que JAR via filepath em target/log4j-xxx.jar e você pode fazer a sua coisa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top