JUnit関連の少しコアな話になります。
JUnitではデフォルトでは、実行する際初期処理としてまずテストクラス内のテストメソッドの数だけテストクラスをインスタンス化し、その後各テストメソッドを実行していく、という仕様になっているようです。そしてかつ、各インスタンスはテストクラス内のすべてのテストメソッドが終了するまでインスタンスの破棄は行わないようです。
上記の仕様であるはずだと言う根拠は、テストクラスにコンストラクタを作成し、そこにsysoutを記述することにより確認をしました。
上記の仕様であることが主原因で、Out of Memoryが発生してしまいます。
他にそうなってしまう原因はいくつかあって
・Springを利用していて初期化にメモリを結構使う
・テスト対象のクラスが複雑でテストメソッドの数が多くなる
・パソコンの物理メモリに限界がある
・DJUnitでカバレッジを調査することもあり、またテスティングペアの名前は統一したいので、テスト対象クラスとテストクラスを1対1に対応させたい。
などが挙げられます。VMの実行メモリを大きくしたり、テストクラスを分割してしまうなどの対処療法を行ってきましたが、何とか主原因をつぶす方法は無いものかと質問をした次第です。
(その他、使用しなくなったオブジェクトにnullをセットしたり明示的にgcの実行を指示する等の苦肉の策を行いましたが、ほとんど影響しませんでした)
前置きが長くなりましたが質問は、JUnitでテストを行う際、テストクラス内のテストメソッドの数だけインスタンス化しているものを、あるテストメソッドを実行する直前にインスタンス化し、そのテストメソッドが終了したらそのインスタンスを破棄するような設定はないのか、あればその方法を教えてほしい、ということになします。
だいぶ分かりにくい説明かもしれませんが…。
以上よろしくお願いします。
No.1ベストアンサー
- 回答日時:
やっつけで試してみたら成功しました。
JUnitのソースを変更します。
変更するソースは「junit.framework.TestSuite」です。
1.クラスに内部クラス「LazyInstance 」を追加
static class LazyInstance implements Test {
Class clazz;
String name;
Test instance;
LazyInstance(Class clazz, String name) {
this.clazz = clazz;
this.name = name;
}
public int countTestCases() {
return 1;
}
public void run(TestResult result) {
if (instance == null) {
instance = realCreateTest(clazz,name);
}
instance.run(result);
}
}
2.メソッドcreateTestの中身をコピーしたstaticメソッド「realCreateTest」を追加
(長いので略しますが、createTestメソッドを丸々コピーしてメソッド名だけ「realCreateTest」に変えたものです)
3.メソッドcreateTestを以下のように修正
static public Test createTest(Class theClass,String name) {
LazyInstance li = new lazyInstance(theClass,name);
return li;
}
この回答への補足
記述の通りでできました。
エクリを使用していたため、複数のJUnitjarが存在していたのに気づかず、1つだけ消してそれで全て消したつもりになっていたことが原因でした。
kazsharpさんありがとうございました。
なんかすごいですね…。
ライブラリの中身を変更するという考えは思い浮かびませんでした。
…で、試してみたのですが、うまく行きませんでした。コンストラクタにシスアウトを記述するとテストメソッド実行前にコンストラクタがテストメソッド分呼び出されていました。
私の記述ミスである可能性もあるので、もう少しゆっくり試してみます。ありがとうございました。
ちなみに困っていた現象は
>Springを利用していて初期化にメモリを結構使う
という部分で、使用するクラスをすべてインスタンスとして持つApplicationContextと呼んでいるインスタンスが10MBを超え、テストメソッドが50を超える場合に、実行メモリを500MBにしてもメモリが不足したという現象でした。
で、実はこの件に関しては、static変数に記述し、スレッドをたくさん作られてもインスタンスが1つしか存在しないようにすることにより回避することができました。
しかし、今回の質問の趣旨のJUnitの遅延初期化の話も将来的に使うかもしれない部分であるので、もう少し調べてみたいと思っています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Java初級 引数に適用できません
-
java ジェネリックスに関して
-
String.containsの反対機能はあ...
-
public static void main (Stri...
-
JUnitのテストメソッドごとのメ...
-
JAVAコンパイルができない。
-
javaに"search"という関数 or ...
-
IDLファイルとヘッダーファイル...
-
staticと+=の意味を・・・
-
C言語での文字列より値を抜き出す
-
別クラスのmainメソッドの実行
-
C# でメソッドに送られてきたOb...
-
Android 別javaファイルのメソ...
-
なぜprotected overrideなのか
-
C# インターフェースについて
-
テキストファイルに書かれた文...
-
Javaの関数名が長い?
-
C# 点の描き方をおしえてくだ...
-
Javaのメモリの管理
-
「タイプ初期化子が例外をスロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Java初級 引数に適用できません
-
String.containsの反対機能はあ...
-
レコード件数の表示
-
YYYYMMDD書式の日付に対する適...
-
StringBufferからStringへキャ...
-
Strutsでチェックボックスの値...
-
Java初心者です、エラーの意味...
-
Google Apps Script で getRang...
-
C# でメソッドに送られてきたOb...
-
メソッドの引数に指定されてい...
-
なぜprotected overrideなのか
-
Fileの読み取り専用の解除
-
return new使用時
-
クラスを作るとメソッドの数が...
-
javaに"search"という関数 or ...
-
C# 点の描き方をおしえてくだ...
-
親の親のメソッドを呼ぶには?
-
Javaの関数名が長い?
-
CSVから読み込んだデータの保持...
-
別クラスのmainメソッドの実行
おすすめ情報