SpringBootでMockMvcを使ったテストを行っていた際、@Autowiredしたオブジェクトが各テストで共通になってしまう問題への対応です。
DIコンテナを利用しているのでオブジェクトが共通になるのは当然として、テスト後に@Beforeや@BeforeClassを付与したメソッドで初期状態に戻るようコードを書くのも変な感じ。
色々調べたところ@DirtiesContextを付与すると、DIコンテナの中身が破棄されるようです。
以下のようにテストクラス宣言前に記述した場合は、クラス内の全メソッド実行後にDIコンテナが破棄されます。
@DirtiesContext
public class 〇〇Test {
...
}
以下のようにテストメソッド前に記述した場合は、テストメソッド実行後にDIコンテナが破棄されます。
public class 〇〇Test {
@DirtiesContext
public void 〇〇_テストする() {
...
}
...
}
もう少し詳しく調べると、クラスの前に付与した場合とメソッドの前に付与した場合でモードが変更できるようです。
| BEFORE_CLASS | クラスモードで指定。クラス内のテストメソッドを実行する前に1度だけDIコンテナを破棄する。 |
| BEFORE_EACH_TEST_METHOD | クラスモードで指定。クラス内の全メソッドごと、実行前に各々DIコンテナを破棄する。 |
| BEFORE_METHOD | メソッドモードで指定。テストメソッド実行前にDIコンテナを破棄する。 |
| AFTER_METHOD | メソッドモードで指定。テストメソッド実行後にDIコンテナを破棄する。 |
| AFTER_EACH_TEST_METHOD | クラスモードで指定。クラス内の全メソッドごと、実行後に各々DIコンテナを破棄する。 |
| AFTER_CLASS | クラスモードで指定。クラス内のテストメソッドを実行した後に1度だけDIコンテナを破棄する。 |
クラスモードのデフォルト値はAFTER_CLASS、メソッドモードのデフォルト値はAFTER_METHODです。
というわけで、以下の場合はクラス内の全テストメソッド実行後にDIコンテナが破棄されます。
@DirtiesContext
public class 〇〇Test {
...
}
以下の場合はテストメソッド実行後にDIコンテナが破棄されます。
public class 〇〇Test {
@DirtiesContext
public void 〇〇_テストする() {
...
}
...
}
挙動を変更したい場合の記述は以下のようになります。
クラス内の全メソッドに対して、実行後にDIコンテナを破棄する。
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class 〇〇Test {
...
}
実行前にDIコンテナを破棄する。
public class 〇〇Test {
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
public void 〇〇_テストする() {
...
}
...
}
テストメソッド全部に@DirtiesContextを付与するのは面倒なので、今回はクラス宣言の前に「@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)」を付与して対応しました。
hierarchyModeというのもあるようですが、今回は使わなそうなので必要になったら調べる感じで。。。
詳しくはAnnotation Type DirtiesContextのjavadocを参照のこと。
