klc
klc

Reputation: 315

Spring integration test - AuthenticationPrincipal not injected

I am trying to use kotlin in my project, which is REST API endpoints serving angularjs frontend. And I use spring rest doc for our api document.

While migrating, I find my security context is not injected in test case.

Test class with mockito-kotlin (mostly converted by Intellij):

@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration(classes = arrayOf(MockAppConfig::class))
@WebAppConfiguration
class UserLoginDocumentation {

@get:Rule
var restDocumentation = JUnitRestDocumentation("target/generated-snippets")

private var mockMvc: MockMvc? = null

@Autowired
private val context: WebApplicationContext? = null

@Before
fun setUp() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context!!)
            .apply<DefaultMockMvcBuilder>(documentationConfiguration(this.restDocumentation)
            .uris().withScheme("https").withHost("myhost.com").withPort(443)).build()
    val authentication = TestingAuthenticationToken(MyUserDetailsService.MyUserDetails(1L), null)
    SecurityContextHolder.getContext().authentication = authentication
}

@Autowired
lateinit var userLoginService: UserLoginService

@Test
@Throws(Exception::class)
fun loginTest() {

    whenever(userLoginService!!.getUserInfo(any(), any(), any())).thenReturn(LoginUserInfo())
    this.mockMvc!!.perform(post("/myloginURL/user")//the remaining is not important....

The controller:

@RequestMapping("/myloginURL")
@RestController
class UserLoginController
@Autowired constructor(
    val userLoginService: UserLoginService) {

@ResponseStatus(HttpStatus.OK)
@RequestMapping(value = "/user", method = arrayOf(RequestMethod.POST), produces = arrayOf(MediaType.APPLICATION_JSON_VALUE))
fun getUser(@AuthenticationPrincipal userDetail: MyUserDetails, 
    request: HttpServletRequest, @RequestParam lang: String): LoginUserInfo? {
    return userLoginService.getUserInfo(userDetail.userId, request.getHeader("Authorization"), lang)
}

}

Here userDetail is not null, but userDetail.userId is null. So it looks like the authentication in test class is not injected into the controller call.

Did I do something wrong, or how to fix it?

Upvotes: 2

Views: 2216

Answers (1)

klc
klc

Reputation: 315

I should use MockMvcBuilders.webAppContextSetup(this.context!!) .apply(springSecurity(springSecurityFilterChain))

springSecurityFilterChain is autowired with @EnableWebSecurity

after that i can use csrf and user i want, the userDetail is injected into the controller.

reference: http://docs.spring.io/spring-security/site/docs/current/reference/html/test-mockmvc.html#test-mockmvc-setup

Upvotes: 1

Related Questions