以前にControllerをテストする記事を書きました。しかし、SpringBootTest
の使い方しか分からなかったので、WebMvcTest
のやり方を理解していませんでした。
ですが、ToshiakiMaki@makingさんのサポートにより、なんとかWebMvcTest
でのテストができるようになったので記事にします。
twitter.comAuthentication authentication = ...
— Toshiaki Maki (@making) 2020年12月11日
TestSecurityContextHolder.setAuthentication(authentication);
だけでもいけませんか?
ゴール
- Spring Securityがある状態でControllerのテストを行う
- WebMvcTestでテストを行う
環境
- Java
- 15
- org.springframework.boot:spring-boot-starter-Web
- 2.4.0
- org.springframework.boot:spring-boot-starter-test
- 2.4.0
- org.springframework.boot:spring-boot-starter-security
- 2.4.0
- org.springframework.security:spring-security-test
- 5.4.1
- (lombok)
テストクラスを準備する
WebMvcTestを使用します。アノテーションの変数のcontrollersにテスト対象のコントローラを指定してください。
テストでHTTP通信を行うために、mockMvcを@Autowiredでインジェクションします。
MockBeanはテスト対象のクラスにモックをインジェクションするために使用します。純粋なコントローラのみのテストを行いたいので、テスト対象以外のクラスをモックしています。
TestSecurityContextHolder.setAuthenticationに値を設定することで、BASIC認証がされている状態でテストを行えます。前回の記事ではこのBASIC認証が上手くいっていなかったです。
AuthTargetUserクラスはSpringSecurityを拡張した際に使用した自作クラスです。ですので、こちらにクラスに関しては参考になりませんので、注意してください。
@WebMvcTest(controllers = IndexController.class) class IndexController2Tests { @Autowired private MockMvc mockMvc; @MockBean private TodoRepository todoRepository; @BeforeEach void setup() { AuthTargetUser user = new AuthTargetUser(new User("user", "pass", Collections.emptyList())); Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities()); TestSecurityContextHolder.setAuthentication(authentication); } }
GETをテストする
GETの場合、通常のControllerのテストと同等のやりで大丈夫です。たぶん。
@Test void test_01() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/")) // レスポンスのステータスコードが200であることを検証する .andExpect(status().isOk()) .andExpect(view().name("index")) .andExpect(model().attribute("todos", Collections.EMPTY_LIST)) ; }
POSTをテストする
デフォルトのSpringSercurityを導入していると、CSRFトークンが必要です。試してはいませんが、CSRFが不要な設定にしていれば、特にテストは不要だと思います。
他にもSpringSecurityの設定を追加している場合は、withで必要な情報を渡す必要があります。
@Test void test_01() throws Exception { mockMvc.perform(MockMvcRequestBuilders.post("/") .with(csrf()) // CSRFのトークン .param("add", "add") .param("id", "123") .param("userId", "user") .param("action", "actionする") ) .andExpect(status().isFound()); }
ソースコード
終わりに
SpringSecurityに不慣れなこともあり、ToshiakiMaki@makingさんのサポートがあっても解決に時間がかかってしまいました。
素直に英語を読めればいいんですけど、上手く読めないと解決まで時間かかってしまいますね…。
なんにせよ、WebMvcTest
でのテストができるようになったので、私は満足です。
ToshiakiMaki@makingさん、ありがとうございました。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。
類似記事
きり丸アドベントカレンダー2020 adventar.org
【SpringBoot】Controllerのテストを行う(Not RestController) nainaistar.hatenablog.com