テスト目的でフィールドの値を変更するのに問題があります。
シングルトンに関する問題はありますが、ログ ファイル マネージャーに使用したいと考えています。設計をやり直す必要があるかどうか実際に考えましたが、私の決定はおそらく問題ないと喜んで承認されました.
でもテストしたい。特に、コードが Windows と Linux で実行されている場合、そしておそらく他の場所で実行されている場合は、今は考えられません。
アイデアは、現在のディレクトリに「testlogs」という名前のテスト用ディレクトリを作成し、それを削除して再生することです。したがって、少なくとも現在のディレクトリに書き込み権限があることを確認するか、ログファイルが書き込まれないことをユーザーに通知するか、別の場所を選択するように求めることができます。
次のコードでは、「ログ」ディレクトリを取得し続けます。本当の「ログ」(存在する場合)を惜しまないようにしたいと思います。
の値を変更できないのはなぜdirname
ですか?
package com.home.app.logger.LogsMngr;
public class LogsMngr {
private static class Holder {
public static String dirname = "logs";
public static final LogsMngr INSTANCE = new LogsMngr(dirname);
}
private LogsMngr(String dirname){
createDirectory(dirname);
}
private createDirectory(String dirname) {
// logic to create a directory on the filesystem
}
public static LogsMngr getInstance() {
return Holder.INSTANCE;
}
}
@RunWith(SeparateClassLoaderRunner.class)
public class Test {
LogsMngr lmngr;
@Test
public void test() {
try {
// Remove existing directory
TUtils.rmfDirectory("testlogs");
// Set directory name
String className = "com.home.app.logger.LogsMngr$Holder";
Class[] memberClasses = LogsMngr.class.getDeclaredClasses();
Field dirnamefield = null;
for(int i=0; i<memberClasses.length; i++) {
if(memberClasses[i].getName().equals(className)) {
dirnamefield = memberClasses[i].getField("dirname");
}
}
//TODO catch NullPointerException because of dirname?
// To prevent from IllegalAccessException:
dirnamefield.setAccessible(true);
// Set test directory
dirnamefield.set(null, "testlogs");
// Create
lmngr = LogsMngr.getInstance();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
参考文献:
SeparateClassLoaderRunner.class
JUnitを使用してプライベートメソッドでクラスをテストする適切な方法は何ですか?
リフレクションを使用して、Java クラスの宣言された内部クラスを検出できますか?
解決:
package com.home.app.logger.LogsMngr;
public class LogsMngr {
private static String dirname = "logs"; <-- moved out of Holder
private static class Holder {
public static final LogsMngr INSTANCE = new LogsMngr(dirname);
}
private LogsMngr(String dirname){
createDirectory(dirname);
}
private createDirectory(String dirname) {
// logic to create a directory on the filesystem
}
public static LogsMngr getInstance() {
return Holder.INSTANCE;
}
}
@RunWith(SeparateClassLoaderRunner.class)
public class Test {
LogsMngr lmngr;
@Test
public void test() {
try {
// Remove existing directory
TUtils.rmfDirectory("testlogs");
Field dirnamefield = LogsMngr.class.getDeclaredField("dirname");
// To prevent from IllegalAccessException:
dirnamefield.setAccessible(true);
// Set test directory
dirnamefield.set(null, "testlogs");
// Create
lmngr = LogsMngr.getInstance();
}
catch(Exception e) {
e.printStackTrace();
}
}
}