Javaプロジェクトがあります。それぞれメインソースとテストソースを含むsrc/main/Java
とsrc/test/Java
ディレクトリがあります(すべてが標準です) 。
ここで、プロジェクトをJava 9.に移行します。src/main/Java
コンテンツはJava 9モジュール;ほぼ同じように見えるcom/acme/project/module-info.Java
があります。この:
module com.acme.project {
require module1;
require module2;
...
}
テストコードにmodule-info.Java
が必要な場合はどうなりますか?たとえば、本番コードではなく、テストにのみ必要なモジュールへの依存関係を追加します。そのような場合、モジュールに別の名前を付けてmodule-info.Java
をsrc/test/Java/com/acme/project/
に配置する必要があります。このように、Mavenはメインソースとテストソースを異なるモジュールとして扱うため、メインモジュールからテストモジュールにパッケージをエクスポートする必要があります。テストモジュールには次のようなパッケージが必要です。
メインモジュール(src/main/Java/com/acme/project
内):
module prod.module {
exports com.acme.project to test.module;
}
テストモジュール(src/test/Java/com/acme/project
内):
module test.module {
requires junit;
requires prod.module;
}
これにより
[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
1つのパッケージが2つのモジュールで定義されているためです。そのため、メインモジュールとテストモジュールで異なるプロジェクトを使用する必要がありますが、これは便利ではありません。
私は間違った道をたどっていると感じます、それはすべて非常にいように見え始めます。テストコードに独自のmodule-info.Java
を含めるには、またはそれなしで同じ効果(require
など)を実現するにはどうすればよいですか。
モジュールシステムは製品コードとテストコードを区別しないため、テストコードをモジュール化する場合、prod.module
そしてその test.module
は同じパッケージを共有できませんcom.acme.project
、 specs で説明されているとおり:
非干渉— Javaコンパイラ、仮想マシン、およびランタイムシステムは、パッケージを含むモジュールが2つの異なるモジュールに同じ名前のパッケージが含まれる場合、各モジュールの観点から、そのパッケージ内のすべてのタイプとメンバーはそのモジュールによってのみ定義されます。あるモジュールでは、他のモジュールのパッケージプライベートタイプまたはそのパッケージのメンバーにアクセスできないようにする必要があります。
Alan Batemanが示すように、Mavenコンパイラプラグインは、src/test/Javaツリーでコードをコンパイルするときにモジュールシステムによって提供される -patch-moduleおよびその他のオプション を使用するため、テスト対象のモジュールはテストクラスで強化されました。また、これは、テストクラスの実行時にSurefireプラグインによって実行されます( named Java 9モジュール でのユニットテストの実行のサポートを参照)。これは、必要ないことを意味します。モジュールにテストコードを配置します。
実装しようとしているプロジェクト設計を再考したいかもしれません。モジュールとそのテストをプロジェクトに実装しているため、モジュールごとに異なるモジュールを使用することは控えなければなりません。
1つのシングルmodule-info.Java
モジュールおよび対応するテストの場合。
関連するプロジェクト構造は次のようになります。
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
どこ module-info.Java
はさらに:-
module com.acme.project {
requires module1;
requires module2;
// requires junit; not required using Maven
}
あなたの質問に従って上記のすべてを要約するだけです-
私は間違った道をたどっていると感じます、それはすべて非常にいように見え始めます。 test-codeに独自のmodule-info.Javaを含めるにはどうすればよいですか、またはそれなしで同じ効果(必須など)を実現するにはどうすればよいですか?
はい、テストコードの異なるモジュールを管理して複雑にすることを考慮すべきではありません。
次のようなディレクティブを使用して、junit
を コンパイル時の依存関係 として扱うことにより、同様の効果を実現できます。
requires static junit;
Mavenを使用すると、上記の構造に従ってmaven-surefire-plugin
これは、テストを単独でモジュールにパッチ適用します。
詳細を追加します。
Java 9以降)jarファイル(またはクラスを含むディレクトリ)は、クラスパス(以前のように)またはモジュールパスに置かれます。クラスパスに追加される場合、そのモジュール情報無視され、モジュールに関連する制限(何を読み取るか、何をエクスポートするかなど)は適用されません。ただし、jarがモジュールパスに追加されると、モジュールとして扱われるため、そのモジュール情報が処理されます。追加のモジュール関連の制限が実施されます。
現在(バージョン2.20.1)、maven-surefire-pluginは古い方法でのみ動作するため、テスト対象のクラスをクラスパスに配置し、module-pathは無視されます。そのため、現時点では、Mavenプロジェクトにmodule-infoを追加しても、Mavenを使用して実行されるテスト(surefireプラグインを使用)で何も変わらないはずです。
私の場合、コマンドラインは次のようになります。
/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
テスト対象のクラスはモジュールとして追加されないため、クラスパス上にあります。
現在、 https://issues.Apache.org/jira/browse/SUREFIRE-1262 で作業が進行中です(SUREFIRE-1420はSUREFIRE-1262の複製としてマークされています)モジュールパスでコードをテストするためのsurefireプラグインを教えます。終了してリリースされると、モジュール情報が考慮されます。ただし、テスト対象のモジュールがjunitモジュールを自動的に読み取るようにする場合(SUREFIRE-1420が示唆するように)、module-info(メインモジュール記述子)はjunit(テストにのみ必要)への参照を含める必要はありません。 。
履歴書:
require static
を使用して)追加できます。 @nullpointerによって提案されました。この場合、Mavenモジュールは、あまり気に入らないコンパイル(テストではない)スコープを使用して、テスト専用モジュールを提供するアーティファクトに依存する必要があります。