ログイン機能実装後のテストについて
ログイン機能実装後のテストで嵌ってしまったので、備忘録として残す。
嵌ったこと
SpringBootでWebアプリを作成した後、認証機能を追加しテストを行ったときに、getメソッドのテストでは認証認可のテストは成功しているのに、postメソッドのテストでは403が返ってきて、認可にエラーが発生してしまった。
試したこと
走らせたコードを抜粋して示す。
@Test
void test() throws Exception {
mockMvc.perform(get("/cart")
.with(user(userDetails)))
.andExpect(status().isOk())
}
ステータスコードは200を返し、テストは通過する。
認証認可も問題なし。
次は以下のテストを走らせた。
@Test
void test() throws Exception {
mockMvc.perform(post("/cart/add")
.param("productId", 1)
.with(user(userDetails)))
.andExpect(status().is3xxRedirection())
}
302のステータスコードが返ってくることを期待したが、403が返ってきた。
「テスト1」では認証認可は問題なしだったのになぜ?
SecurityConfigを確認しても権限の設定は間違ってはいない、、、
調べてみると
Spring SecurityのCSRF機能を有効にしている場合は、POSTのHTTPメソッドを使用したリクエストに対して自動的にCSRFトークンチェックが行なわれる。そのため、HTTPメソッドを使用してリクエストを行なうには、有効なCSRFトークン値をリクエストパラメータまたはリクエストヘッダーに含める必要があるとのこと。
「テスト2」に有効なCSRFトークン値をリクエストパラメータに設定し、再度テストを走らせてみた。
@Test
void test() throws Exception {
mockMvc.perform(post("/cart/add")
.param("productId", 1)
.with(csrf()) // csrfメソッドを追加
.with(user(userDetails)))
.andExpect(status().is3xxRedirection())
}
今度は302のステータスコードが返ってきて、無事テストが通過した。
まとめ
postメソッドのテストを行う場合は、CSRFトークン値をリクエストパラメータに含める。
参考