vendredi 10 août 2018

Testing Spring Controller POST method after adding Spring Security on Kotlin

I'm developing a Spring Boot application with Kotlin. I recently added Spring Security as a dependency and now I'm not able to test my Controllers anymore.

This is my controller:

@RestController
@RequestMapping("/users", produces = [MediaType.APPLICATION_JSON_UTF8_VALUE])
class UserController {
    @Autowired
    lateinit var userService: UserService

    @PostMapping
    fun addUser(@Valid @RequestBody user: User): ResponseEntity<PostUserResponse> {
        userService.addUser(user)
        return ResponseEntity.status(HttpStatus.CREATED).body(PostUserResponse())
    }

    @GetMapping("user/{login}")
    fun getUserByLogin(@PathVariable login: String): ResponseEntity<User> {
        val user = userService.getUserByLogin(login)
        return ResponseEntity.status(HttpStatus.OK).body(user)
    }

    @ExceptionHandler(NoSuchElementException::class)
    fun failedToRetrieveById(exception: NoSuchElementException): ResponseEntity<UserNotFoundResponse> {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(UserNotFoundResponse())
    }
}

And this is my test class:

@ExtendWith(SpringExtension::class)
@WebMvcTest(controllers = [UserController::class])
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class UserControllerTest {
    @MockBean
    private lateinit var userService: UserService

    @Autowired
    private lateinit var context: WebApplicationContext

    private lateinit var mvc : MockMvc

    val login = "test@test.test"
    val password = "password"
    val user = User(login = login, password = password)

    @BeforeAll
    fun setup () {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply<DefaultMockMvcBuilder>(springSecurity())
                .build()
    }

    @Test
    fun `Sending POST to the users endpoint with a valid json creates a new user`() {
        val payload = mapOf(
                "login" to login,
                "password" to password
        )
        Mockito.`when`(userService.addUser(user))
                .thenReturn(user)


        mvc.perform(MockMvcRequestBuilders.post("/users")
                .with(csrf().asHeader())
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(JSONObject(payload).toString()))
                .andExpect(MockMvcResultMatchers.status().isCreated)
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8))
    }
}

My code mimics the example that can be found here: https://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#test-mockmvc-smmrpp

But still the HTTP code of the reply is 401.

It's interesting to notice that removing the line:

.with(csrf().asHeader())

Makes the server reply with a 403 instead of a 401. How to generate a valid request?

Aucun commentaire:

Enregistrer un commentaire