今回は、Junitでテスト時にコントローラでUserDetailsを@AuthenticationPrincipalで受け取る方法についてみていきたいと思います。
困っていたところ
Controller
@Controller
public SomeController {
@Autowired
private SomeService someService;
@GetMapping("/some")
public String some(@AuthenticationPrincipal CustomUserDetails user) {
someService.someMethod(user.getSomeData());
return "some/page";
}
}
- 上記のコードは例です。
上記のように「AuthenticationPrincipal」アノテーションがついているUserDetailsからSomeDataを取得してServiceに渡していました。
Test
public class SomeControllerTest {
@InjectMocks
private SomeController someController;
@Mock
private SomeService someService;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(itemEndpoint)
.build();
}
@Test
public void someTest() throws Exception {
when(someService.someMethod(anyString())).thenReturn("some"); // こちら
mockMvc.perform(get("/some")).
.andExpect(status().isOk());
}
}
「こちら」となっている箇所でモック化するときにNullPointExceptionとなり、調べたところコントローラのCustomUserDetailsがNullで「user.getSomeData()」するときにエラーが発生していました。
UserDetailsのモック化
public class SomeControllerTest {
@InjectMocks
private SomeController someController;
@Mock
private SomeService someService;
private MockMvc mockMvc;
private HandlerMethodArgumentResolver putAuthenticationPrincipal = new HandlerMethodArgumentResolver() {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(CustomUserDetails.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return new CustomUserDetails(…);
}
};
@BeforeEach
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(itemEndpoint)
.setCustomArgumentResolvers(putAuthenticationPrincipal)
.build();
}
@Test
public void someTest() throws Exception {
when(someService.someMethod(anyString())).thenReturn("some");
mockMvc.perform(get("/some")).
.andExpect(status().isOk());
}
}
- 赤文字と表示している箇所が追加したところで、使用しているカスタムのUserDetailsのクラス名を指定すればOKです。
- その後は定義したResolverをMockMvcんみ登録する必要があるので、登録しました。
これで正常に動きました。
終わりに
SpringSecurityテストの「WithAnonymousUser」「WithUserDetails」「WithMockUser」などのアノテーションもありますが、今回の状況とは違ったのでパスしました。機会があれば調べたいと思います。
Junit難しい。。。
