「外部ファイルを読み込むモジュールのJUnitを書きたいんすけど、指定するファイル名のパスって固定でいいですか?」と聞かれたので、「もちろんNG」と伝えた内容をメモします。
NG理由
- プロジェクトファイルの位置を変えると、ユニットテストができなくなるため
- 他人がモジュールをチェックアウトした際に、ユニットテストができなくなるため
- Jenkins等のCIツールでユニットテストができなくなるため(一番イタイ)
結論 クラスローダからファイルの位置を特定してください。
Mavenプロジェクトだと、ソースファイルはsrc/main下、ユニットテスト用ファイルはsrc/test下に配置されます。
/src
/main
/java
/resources
/test
/java
/resources
test配下のモジュールはmvn test時のみクラスパスに追加されます。そのため、JUnit試験で使用するファイルは src/test/resources 配下に置くと良いことがわかります。
外部ファイル名を指定する
こんなメソッドの試験を行いたいです。XMLファイル名を指定すると、それを読み込みBeanを生成するメソッドです。
public TestBean readXml(String xmlFileName) throws XMLReadException;
この様にファイル名をパス固定にしてしまうと、上記のNG理由にあてはまり、ポータビリティがなくなります。
/// NG例
@Test
public void readTest() throws Exception {
TestBean bean = readXml("/path/to/project/src/test/resources/test.xml");
assertNotNull(bean);
assertEquals("test.xml", bean.getOriginName());
...
}
こういう場合は、クラスローダにファイルの場所を教えてもらいます。
/// OK例
@Test
public void readTest() throws Exception {
//- クラスローダから test.xml のファイル位置を取得
//- クラスローダに指定するクラスは何でも良いが、自クラスを指定すると良さそう
String fileName = XXXX.class.getClassLoader().getResource("test.xml").getPath();
//- あとは同じように試験する
TestBean bean = readXml(fileName);
assertNotNull(bean);
assertEquals("test.xml", bean.getOriginName());
...
}
クラスローダがクラスパスにあるファイルを探しだし(getResourceメソッド)、その戻りがURLなので getPath()で実際のパスを取得しています。
これで、様々なディレクトリや環境でユニットテストを実行することができます。