unitarias tutorial que pruebas plugin example español compiler java maven junit java-9 java-module

tutorial - pruebas unitarias java eclipse



Java 9+maven+junit: ¿el código de prueba necesita un módulo-info.java propio y dónde colocarlo? (3)

Añadiendo algunos detalles.

En Java desde 9, un archivo jar (o un directorio con clases) puede colocarse en classpath (como anteriormente) o en la ruta del módulo. Si se agrega a classpath, su módulo-info se ignora y no se aplican restricciones relacionadas con el módulo (qué lee qué, qué exporta qué, etc.). Sin embargo, si se agrega un tarro a la ruta del módulo, se trata como un módulo, por lo que su módulo de información se procesa y se aplicarán restricciones adicionales relacionadas con el módulo.

Actualmente (versión 2.20.1), maven-surefire-plugin solo puede funcionar de la forma anterior, por lo que coloca las clases que se están probando en classpath y se ignora la ruta del módulo. Entonces, en este momento, agregar información de módulo a un proyecto de Maven no debería cambiar nada con las pruebas que se ejecutan con Maven (con el complemento surefire).

En mi caso, la línea de comando es como la siguiente:

/bin/sh -c cd /home/rpuch/git/my/test-java9-modules-junit && /home/rpuch/soft/jdk-9/bin/java --add-modules java.se.ee -jar /home/rpuch/git/my/test-java9-modules-junit/target/surefire/surefirebooter852849097737067355.jar /home/rpuch/git/my/test-java9-modules-junit/target/surefire 2017-10-12T23-09-21_577-jvmRun1 surefire8407763413259855828tmp surefire_05575863484264768860tmp

Las clases en prueba no se agregan como un módulo, por lo que están en classpath.

Actualmente, se está realizando un trabajo en https://issues.apache.org/jira/browse/SUREFIRE-1262 (SUREFIRE-1420 está marcado como un duplicado de SUREFIRE-1262) para enseñar el plugin surefire a poner el código bajo prueba en el módulo camino. Cuando esté terminado y liberado, se considerará un módulo-información. Pero si hacen que el módulo bajo prueba lea el módulo junit automáticamente (como sugiere SUREFIRE-1420), el módulo-información (que es un descriptor principal del módulo) no tendrá que incluir una referencia a junit (que solo es necesario para las pruebas) .

Un resumen:

  1. El módulo de información solo necesita ser agregado a las fuentes principales.
  2. por el momento, surefire ignora la nueva lógica relacionada con el módulo (pero esto se cambiará en el futuro)
  3. (cuando los módulos funcionarán en pruebas seguras ) probablemente no será necesario agregar junit a la información del módulo
  4. (cuando los módulos funcionarán en pruebas seguras) si las pruebas exigen algún módulo (y solo por ellas), se puede agregar como una dependencia de solo compilación (usando require static ), como sugiere @nullpointer. En este caso, el módulo de Maven tendrá que depender de un artefacto que suministre ese módulo solo de prueba utilizando el alcance de compilación (no de prueba) que no me gusta mucho.

Digamos que tengo un proyecto Java utilizando Maven 3 y Junit. Hay directorios src/main/java y src/test/java que contienen las fuentes principales y las fuentes de prueba, respectivamente (todo es estándar).

Ahora quiero migrar el proyecto a Java 9. El contenido de src/main/java representa el módulo de Java 9; hay com/acme/project/module-info.java aspecto similar al siguiente:

module com.acme.project { require module1; require module2; ... }

¿Qué pasa si el código de prueba necesita un module-info.java propio? Por ejemplo, para agregar una dependencia en algún módulo que solo se necesita para las pruebas, no para el código de producción. En tal caso, tengo que poner module-info.java a src/test/java/com/acme/project/ dando al módulo un nombre diferente. De esta manera, Maven parece tratar las fuentes principales y las fuentes de prueba como módulos diferentes, así que tengo que exportar paquetes desde el módulo principal al módulo de prueba, y requerir paquetes en el módulo de prueba, algo como esto:

módulo principal (en src/main/java/com/acme/project ):

module prod.module { exports com.acme.project to test.module; }

módulo de prueba (en src/test/java/com/acme/project ):

module test.module { requires junit; requires prod.module; }

Esto produce

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project test-java9-modules-junit: Compilation failure: Compilation failure: [ERROR] /home/rpuch/git/my/test-java9-modules-junit/src/test/java/com/acme/project/GreeterTest.java:[1,1] package exists in another module: prod.module

Porque un paquete está definido en dos módulos. Así que ahora tengo que tener diferentes proyectos en el módulo principal y el módulo de prueba, lo cual no es conveniente.

Siento que sigo el camino equivocado, todo comienza a verse muy feo. ¿Cómo puedo tener un module-info.java propio en el código de prueba, o cómo puedo lograr los mismos efectos ( require , etc.) sin él?


El sistema de módulos no distingue entre el código de producción y el código de prueba, por lo que si elige modularizar el código de prueba, prod.module y test.module no pueden compartir el mismo paquete com.acme.project , como se describe en las specs :

Sin interferencias : el compilador de Java, la máquina virtual y el sistema en tiempo de ejecución deben garantizar que los módulos que contienen paquetes del mismo nombre no interfieran entre sí. Si dos módulos distintos contienen paquetes con el mismo nombre, entonces, desde la perspectiva de cada módulo, todos los tipos y miembros de ese paquete están definidos solo por ese módulo. El código en ese paquete en un módulo no debe poder acceder a los tipos de paquetes privados o miembros en ese paquete en el otro módulo.

Como lo indica Alan Bateman, el complemento del compilador de Maven utiliza --patch-module y otras opciones proporcionadas por el sistema de módulos cuando compila el código en el árbol src / test / java, de modo que el módulo bajo prueba se complementa con las clases de prueba. Y esto también lo hace el complemento Surefire cuando se ejecutan las clases de prueba (consulte Soporte en la ejecución de pruebas unitarias en los módulos Java 9 con nombre ). Esto significa que no necesita colocar su código de prueba en un módulo.


Es posible que desee repensar el diseño del proyecto que está intentando implementar . Ya que está implementando un módulo y su prueba en un proyecto, debe abstenerse de usar módulos diferentes para cada uno de ellos individualmente.

Debe haber un solo módulo- module-info.java para un módulo y sus pruebas correspondientes.

Su estructura de proyecto relevante podría verse así:

Project/ |-- pom.xml/ | |-- src/ | |-- test/ | | |-- com.acme.project | | | |-- com/acme/project | | | | |-- SomeTest.java | | | |-- main/ | | |-- com.acme.project | | | |-- module-info.java | | | |-- com/acme/project | | | | |-- Main.java

donde el module-info.java podría ser: -

module com.acme.project { requires module1; requires module2; // requires junit; not required using Maven }

Sólo para resumir todo lo anterior según sus preguntas:

Siento que sigo el camino equivocado, todo comienza a verse muy feo. ¿Cómo puedo tener un módulo-info.java propio en el código de prueba, o cómo puedo lograr los mismos efectos (requerir, etc.) sin él?

, no debe considerar la administración de diferentes módulos para el código de prueba, lo que lo hace complejo.

Puede lograr un efecto similar al tratar a junit como una dependencia en tiempo de compilación usando las directivas de la siguiente manera:

requires static junit;

Usando Maven puede lograr esto siguiendo la estructura mencionada anteriormente y utilizando el maven-surefire-plugin que se encargaría de parchear las pruebas al módulo por sí mismo.