web-dev-qa-db-ja.com

Java 9 + maven + junit:テストコードには、独自のmodule-info.Javaとそれを配置する場所が必要ですか?

Javaプロジェクトがあります。それぞれメインソースとテストソースを含むsrc/main/Javasrc/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.Javasrc/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など)を実現するにはどうすればよいですか。

29

モジュールシステムは製品コードとテストコードを区別しないため、テストコードをモジュール化する場合、prod.module そしてその test.moduleは同じパッケージを共有できませんcom.acme.projectspecs で説明されているとおり:

非干渉— Javaコンパイラ、仮想マシン、およびランタイムシステムは、パッケージを含むモジュールが2つの異なるモジュールに同じ名前のパッケージが含まれる場合、各モジュールの観点から、そのパッケージ内のすべてのタイプとメンバーはそのモジュールによってのみ定義されます。あるモジュールでは、他のモジュールのパッケージプライベートタイプまたはそのパッケージのメンバーにアクセスできないようにする必要があります。

Alan Batemanが示すように、Mavenコンパイラプラグインは、src/test/Javaツリーでコードをコンパイルするときにモジュールシステムによって提供される -patch-moduleおよびその他のオプション を使用するため、テスト対象のモジュールはテストクラスで強化されました。また、これは、テストクラスの実行時にSurefireプラグインによって実行されます( named Java 9モジュール でのユニットテストの実行のサポートを参照)。これは、必要ないことを意味します。モジュールにテストコードを配置します。

8
manouti

実装しようとしているプロジェクト設計を再考したいかもしれません。モジュールとそのテストをプロジェクトに実装しているため、モジュールごとに異なるモジュールを使用することは控えなければなりません。

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これは、テストを単独でモジュールにパッチ適用します。

7
Naman

詳細を追加します。

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(テストにのみ必要)への参照を含める必要はありません。 。

履歴書:

  1. module-infoをメインソースに追加するだけです
  2. 当分の間、surefireは新しいモジュール関連のロジックを無視します(ただし、これは将来変更される予定です)
  3. (モジュールが確実なテストの下で動作するとき) junitはおそらくmodule-infoに追加する必要はないでしょう
  4. (モジュールが確実な火災テストの下で動作するとき)いくつかのモジュールがテストで必要な場合(そしてそれらだけで)、それはコンパイル専用の依存関係として(require staticを使用して)追加できます。 @nullpointerによって提案されました。この場合、Mavenモジュールは、あまり気に入らないコンパイル(テストではない)スコープを使用して、テスト専用モジュールを提供するアーティファクトに依存する必要があります。
2