Я пытаюсь написать интеграционный тест, который достигает конечной точки REST и получает данные для определенного пользователя, прошедшего проверку подлинности (тот, который я настраиваю в тесте). Сначала я попробовал свою настройку с mockMvc = webAppContextSetup(wac).apply(springSecurity()).build()
, но это постоянно терпело неудачу с BeanInstantiationException
. С помощью тестирования Spring Security и MvcMock с использованием пользовательского Реализация UserDetails, мне удалось решить эту проблему, переключив файл setUp. Теперь, когда я переключил свои настройки на использование standaloneSetup
, я могу вызывать свой контроллер. Но что бы я ни делал, я не могу получить пользовательский объект UserDetails, который я создаю в своем тесте, в метод в моем контроллере, на котором заканчивается вызов MockMvc.
Я использую Spring 4.2.2 и Spring Security 4.0.1.
Мой тестовый код выглядит примерно так:
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { RestControllerITConfig.class })
@WebAppConfiguration
public class ControllerIT {
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = standaloneSetup(new Controller())
.setCustomArgumentResolvers(new AuthenticationPrincipalArgumentResolver())
.build();
}
@Test
public void testGetEndpoint() throws Exception {
CustomUserDetails userDetails = new CustomUserDetails("John","Smith", "abc123");
assertNotNull(userDetails);
MvcResult result = mockMvc.perform(
get("/somepath").with(user(userDetails)))
.andExpect(status().isOk())
.andExpect(content().contentType("text/json")));
}
}
@Configuration
@ComponentScan(basePackageClasses = { AuthenticationConfig.class })
public class RestControllerITConfig {
}
@Configuration
@EnableWebSecurity
@ComponentScan("com.my.authentication.package")
public class AuthenticationConfig extends WebSecurityConfigurerAdapter {
// snip
}
@Target({ ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface MyUser {
}
@RestController
@RequestMapping("/somepath")
public class Controller {
@RequestMapping(value = "", method = RequestMethod.GET)
public ResponseEntity<Object> getSomePath(@MyUser CustomUserDetails customUser) {
customUser.getName(); // <== Causes NPE
}
}
Есть и другие элементы нерелевантной конфигурации, которые для краткости опущены. Я действительно не понимаю, почему пользовательский объект UserDetails, который я явно создал в тесте, не передается в мой контроллер REST, а передается нулевой объект. Что я здесь делаю неправильно? У кого-нибудь есть рабочий пример аналогичного случая? Спасибо заранее.