Utilisation de Maven pour créer des fichiers JAR distincts pour le test unitaire d'un chargeur de classes personnalisé

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

Question

Dans le cadre de mon projet actuel, j'ai créé un chargeur de classes personnalisé. Une partie des tests unitaires du chargeur personnalisé implique l'utilisation de certains fichiers JAR pour démontrer le comportement correct du chargeur.

Je souhaite créer les fichiers JAR de test à partir de sources Java avant d'exécuter les tests unitaires. En outre, les fichiers JAR de test ne peuvent pas figurer sur le chemin de classe lorsque les tests unitaires sont exécutés, car je souhaite les charger de manière dynamique pendant l'exécution du test.

Existe-t-il un modèle standard permettant de réaliser ce type de "construction de JAR latéraux avant la phase de test, tout en les laissant en dehors du chemin d'accès aux classes"? exigence? Je ne peux pas croire que je sois la première personne à essayer cela avec Maven 2, mais je n'arrive pas à comprendre la structure et les dépendances appropriées du POM. D'habitude, certains des fichiers jar de test ne sont pas générés avant la phase de test, mais j'ai également rencontré des problèmes d'incohérence dans l'ordre de fabrication, ce qui a provoqué le bon fonctionnement de la compilation sur une seule machine. tester les bocaux sur un autre.

Était-ce utile?

La solution

La solution la plus simple consiste à configurer un autre projet pour regrouper les classes de votre test jar, puis définissez-le en tant que programme normal. dépendance au test .

Si vous ne voulez pas / ne pouvez pas faire cela, vous pouvez utiliser le plugin assembly pour créer un fichier jar dans la phase process-test-classes (c'est-à-dire une fois les tests terminés). compilé mais avant que les tests ne soient exécutés). La configuration ci-dessous appellera le plug-in d'assembly pour créer un fichier jar appelé classloader-test-deps au cours de cette phase dans le répertoire cible. Vos tests peuvent ensuite utiliser ce fichier au besoin.

Le plug-in d'assembly utilise un descripteur d'assembly (dans src / main / assembly, appelé test-assembly.xml) qui conditionne le contenu de target / test-classes. J'ai configuré un filtre pour inclure le contenu du paquet com.test et de ses enfants. Cela suppose que vous ayez une convention de nom de paquet que vous pouvez appliquer pour le contenu du fichier jar.

Par défaut, le plug-in d'assemblage associera le fichier jar en tant qu'artefact supplémentaire en spécifiant attach comme false, il ne sera ni installé ni déployé.

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

Ceci est le contenu 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>

Autres conseils

J'essaierais de configurer tout ce dont vos tests ont besoin dans le test. Le principal avantage est qu’il n’existe pas de configuration invisible invisible implicite pour le test. Le test peut s'exécuter dans tous les environnements. De plus, il est beaucoup plus facile d'ajouter de nouveaux scénarios strictement isolés car vous ne dépendez pas d'une configuration de scénario mixte.

La configuration ne devrait pas être trop difficile:

  • sérialiser une classe java:
    • avec une bibliothèque d'ingénierie de code de type
    • Vous pouvez également utiliser un fichier de classe Java renommé avec un suffixe de fichier autre que .class. Placez-le dans le dossier de ressources de test et chargez-le avec le chargeur de classes (getResourceAsStream (...)).
  • compresser le fichier de classe (`java.util.zip.GZIPOutputStream`)
  • chargez le fichier de classe avec votre chargeur de classe

Il existe une approche alternative qui utilise la conception du chargeur de classes java et fonctionne sans génération de classes supplémentaires.

Java a une hiérarchie de chargeur de classe. Chaque chargeur de classe a un chargeur de classe parent. La racine de la hiérarchie du chargeur de classes est le chargeur de classes d'amorçage. Quand une classe est chargée avec un chargeur de classes, elle essaiera d’abord de charger la classe avec le chargeur de classe parent, puis elle-même.

Vous pouvez charger la classe de test avec le chargeur de classes actuel. Mettez-le en pot et chargez-le avec votre propre chargeur de classe. La seule différence est que vous définissez le chargeur de classe parent sur celui qui ne peut pas charger votre classe de test.

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 résout l’ordre de construction via l’analyse de dépendance. Par conséquent, vos JAR construisent normalement, car celui qui utilise vos JAR de test les déclare simplement en tant que dépendances. Cependant, les dépendances sont également placées sur le chemin de classe. Le " scope " d'une dépendance détermine quel chemin de classe il continue. Par exemple, les dépendances 'compile' se trouvent sur le chemin d'accès aux classes pour la compilation, le test et l'exécution. les dépendances 'runtime' sont sur le chemin de classe pour les tests et l'exécution; Les dépendances 'test' ne concernent que le chemin d'accès aux classes pendant le test. Malheureusement, vous avez un cas qui n'est couvert par aucune des portées disponibles: vous avez une dépendance, mais vous ne le souhaitez pas dans le chemin d'accès aux classes. C’est un cas d’usage marginal et c’est pourquoi vous avez du mal à trouver des exemples.

Donc, à moins qu'un gourou de Maven ne se lève pour indiquer le contraire, je suggère que c'est impossible sans écrire un plugin spécial Maven. Au lieu de cela, cependant, je recommande autre chose. Avez-vous vraiment besoin de fichiers JAR personnalisés pour tester votre chargeur de classe? Cela me semble louche. Peut-être que vous pouvez utiliser n'importe quel vieux JAR? Si tel est le cas, j'utiliserais le plugin maven-dependency pour copier un fichier JAR réputé toujours se trouver dans votre référentiel (par exemple, log4j) dans le répertoire cible de votre module local. Votre test peut ensuite accéder à ce fichier JAR via le chemin de fichier à target / log4j-xxx.jar et vous pourrez faire votre travail.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top