[解決済み] Spring MVCアプリケーションでAspectをテストする方法
2022-02-18 22:38:51
質問
Spring MVCアプリケーションで、すべてのコントローラメソッドで例外をキャッチするためにAspectを使用しています。
@Component
@Aspect
public class ControllerExceptionAspect {
private Logger logger;
public ControllerExceptionAspect() {
logger = Logger.getLogger(ControllerExceptionAspect.class);
}
public ControllerExceptionAspect(Logger logger) {
this.logger = logger;
}
// Catching all exceptions from all methods in all controllers classes
@AfterThrowing(pointcut = "execution(* com.my.package..controller..*(..))", throwing = "exception")
public void afterThrowingAdvice(Exception exception) {
logger.error("CONTROLLER ASPECT: EXCEPTION IN METHOD -> " +
exception.getClass());
}
}
Aspectは正常に動作していますが、残念ながらテストができません。何度も試してみましたが、コントローラで例外をシミュレートした後、Aspectメソッドが呼び出されたかどうかをキャッチする方法を得ることができません。
@SuppressWarnings("ALL")
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = RootConfig.class),
@ContextConfiguration(classes = WebConfig.class)
})
public class ControllerExceptionAspectTest {
@Autowired
ApplicationContext applicationContext;
@Test
public void testControllerExceptionAspectGetsExecutedWhenExceptionOccures(){
HomeController homeController = (HomeController)applicationContext.getAutowireCapableBeanFactory().getBean("homeController");
try{homeController.callMethod("00000");}
catch (Exception e){}
ControllerExceptionAspect controllerExceptionAspect = (ControllerExceptionAspect)applicationContext.getAutowireCapableBeanFactory().getBean("controllerExceptionAspect");
// HOW TO CATCH THAT ASPECT METHOD WAS CALLED???
}
}
解決方法は?
アスペクト自体をユニットテストするのではなく、作成した設定(アスペクトのポイントカット)をテストしたいということだと思います。残念なことに、それを実現する簡単な方法はないのです。
ネットのアドバイスに従って、ログをキャッチするなどの工夫をするとよいでしょう。正直なところ、私は、アスペクトが呼び出されたことを本当にテストする必要がある場合にのみ、アスペクトの期待される動作をテストします。ログを取るのであれば、私はそれを行いません。dbに何かを設定する場合(またはその他の副作用)には、その値がdbにあるかどうかを確認します。それが統合テストの杜撰なところです。
もし、本当に、本当に、あなたが望む方法でアスペクトをテストしなければならないのなら、与えられたコードと似たようなものを書くことができます。しかし、通常の(テストではない)実行時のSpringの設定は、Springコンテキストに存在するVerifierインターフェースのダミー実装が必要であることを忘れないでください。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Config.class)
public class AspectTesting {
@Autowired
ServiceWithAspect service;
@Autowired
Verifier verifyingAspect;
@Test
public void test() {
// given
boolean condition = false;
// when
try {
service.doit();
} catch (Exception swallow) {}
// then
try {
condition = ((VerifyingAspect) ((Advised) verifyingAspect).getTargetSource().getTarget()).wasExecuted();
} catch (Exception swallow) {}
// then
Assert.assertTrue(condition);
}
}
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("aspects")
class Config {
}
@Component
class VerifyingAspect implements Verifier {
private boolean executed = false;
public boolean wasExecuted() {
return executed;
}
@Override
public void invoked() {
executed = true;
}
}
@Service
class ServiceWithAspect {
public void doit() {
throw new RuntimeException();
}
}
@Component
@Aspect
class TestedAspect {
@Autowired
Verifier verifier;
@AfterThrowing(pointcut = "execution(* *(..))", throwing = "exception")
public void afterThrowingAdvice(Exception exception) {
// your aspect logic here
verifier.invoked();
}
}
interface Verifier {
void invoked();
}
関連
-
[解決済み】StringUtils.isBlank() vs String.isEmpty()
-
[解決済み】スレッド「main」での例外 java.lang.StringIndexOutOfBoundsException: 文字列のインデックスが範囲外です。0 [閉店]
-
[解決済み】keytoolエラー 鍵屋が改ざんされたか、パスワードが不正確だった場合
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] cURLでJSONデータをPOSTするにはどうすればよいですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
-
[解決済み] プライベートメソッド、フィールド、インナークラスを持つクラスをテストするにはどうすればよいですか?
-
[解決済み] Spring Bootアプリケーションにポートを設定する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Hibernateエラー:同じ識別子値を持つ別のオブジェクトがすでにセッションに関連付けられました。
-
[解決済み】代入の左手は必ず変数 CharAt
-
[解決済み】StringUtils.isBlank() vs String.isEmpty()
-
[解決済み】スレッド「main」での例外 java.lang.StringIndexOutOfBoundsException: 文字列のインデックスが範囲外です。0 [閉店]
-
[解決済み] 二項演算子「&」のオペランド型がおかしい java
-
[解決済み】なぜjava.io.Fileにはcloseメソッドがないのでしょうか?
-
[解決済み】デフォルトのキーストアファイルが存在しない?
-
[解決済み】JLabelのテキストを中央に配置するには?
-
[解決済み】Gradleがtools.jarを見つけ出さない
-
[解決済み】Java LinkedListでNodesを使用する