Тестирование метода POST Spring Controller после добавления Spring Security на Kotlin

Я разрабатываю приложение Spring Boot с Kotlin. Недавно я добавил Spring Security в качестве зависимости, и теперь я больше не могу тестировать свои контроллеры.

Это мой контроллер:

@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())
    }
}

А это мой тестовый класс:

@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 = "[email protected]"
    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))
    }
}

Мой код имитирует пример, который можно найти здесь: https://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#test-mockmvc-smmrpp

Но все же HTTP-код ответа - 401.

Интересно отметить, что удаление строки:

.with(csrf().asHeader())

Делает ответ сервера 403 вместо 401.

Моя конфигурация безопасности в основном "пустая". Я не указываю никаких ограничений, поэтому, согласно документации, единственная проблема должна заключаться в предоставлении действительного токена CSRF.

@Configuration
@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
    override fun configure (httpSecurity: HttpSecurity) {
        httpSecurity
                .authorizeRequests()
                .antMatchers("/*")
                .permitAll()
    }
}

Как сгенерировать действительный запрос?

3
0
665
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это сложный вопрос, ответ зависит от вашей конфигурации безопасности.

Но в целом вы должны включить зависимость spring-security-test, и тогда эта документация должен помочь вам пойти дальше.

Спасибо за ваш ответ. Я добавил свою конфигурацию безопасности (которая в настоящее время очень проста) к вопросу. Согласно моему пониманию документации, токен CSRF должен быть единственным требованием, чтобы сделать запрос действительным.

Adriano Todaro 10.08.2018 20:39
401 означает, что запрос сделан неаутентифицированным пользователем. Чтобы изменить это, попробуйте добавить: perform(post("/users").with(user("user"))). Это добавляет пользователя в контекст безопасности, и запрос должен перейти к контроллеру.
Max Farsikov 10.08.2018 20:49

Это сработало. Я не понял, что вы должны указывать пользователя по умолчанию

Adriano Todaro 12.08.2018 15:28

Другие вопросы по теме