結論
RequestPostProcessor
を実装してテスト実行時にremoteAddrを上書きすれば良い。
環境
- kotlin 1.9.22
- spring-boot 3.2.1
- spring-security 6.2.1
SpringSecurityの設定は以下だとします。
SecurityConfig
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.authorizeHttpRequests { authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry
// /dummyへのアクセスは特定のIP(仮にxxx.xxx.xxx.xxxとする)の場合だけ許可する
.requestMatchers("/dummy")
.access(WebExpressionAuthorizationManager("hasIpAddress('xxx.xxx.xxx.xxx')"))
// その他のURLは全て許可する
.anyRequest().permitAll()
return http.build()
}
※Controllerのコードは今回重要でないので割愛します。
テストコード
まずIP制限を考慮せずにUnitTestをMockMvcで以下の様に実装します。
HogeControllerTest
@Test
fun test_ip_restrictions() {
mockMvc
.get("/dummy")
.andExpect {
status { isOk() }
}
}
上記のテストを実行するとIP制限されているためHTTPステータスが403となりテストが失敗します。IP制限を通過させるためにはアクセス元IPをモックする必要があります。
アクセス元IPをモックするには以下のRequestPostProcessor
を実装してrequestをモックする必要がありました。
RequestPostProcessor
package org.springframework.test.web.servlet.request;
import org.springframework.mock.web.MockHttpServletRequest;
@FunctionalInterface
public interface RequestPostProcessor {
MockHttpServletRequest postProcessRequest(MockHttpServletRequest request);
}
今回はRequestUtilsというテスト用のユーティリティーobjectを作成してIPアドレスをモック出来るようにしました。
object RequestUtils {
fun remoteAddr(remoteAddr: String): RequestPostProcessor = RequestPostProcessor { request ->
request.remoteAddr = remoteAddr
request
}
}
先ほどのテストケースを以下の様に修正します。
HogeControllerTest
@Test
fun test_ip_restrictions() {
mockMvc
.get("/dummy") {
// 許可されているIPアドレスを指定する
with(remoteAddr("xxx.xxx.xxx.xxx"))
}
.andExpect {
status { isOk() }
}
}
こうする事でテスト時にIP制限されたURLへのテストを通過させることができます。
許可されているIPアドレス以外からは403エラーとなるテストも書くと良いです。
HogeControllerTest
@Test
fun test_ip_restrictions_forbidden() {
mockMvc
.get("/dummy") {
// 許可されていないIPアドレスを指定する
with(remoteAddr("yyy.yyy.yyy.yyy"))
}
.andExpect {
// 403 error
status { isForbidden() }
}
}
以上です。