Как настроить RestController, но с помощью Spring Mobile (spring-mobile-device)
У меня есть контроллер Rest с устройством (устройство должно быть решено, я использую spring-mobile-device) в качестве параметра. Юнит тест дал мне статус 415.
Вот кодекс
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> authenticationRequest(@RequestBody AuthenticationRequestDto authenticationRequest,
Device device) throws AuthenticationException {
Authentication authentication = this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(), authenticationRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = this.userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
String token = this.tokenGenerator.generateToken(userDetails, device);
return ResponseEntity.ok(new AuthenticationResponseDto(token));
}
Модульный тест
ResultActions res = mockMvc.perform(post("/auth", authentication, device).contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(authentication)));
res.andExpect(status().isOk());
2 ответа
Ну в принципе я был не прав с моей конфигурацией. Обязательно настройте Web Config для тестирования таким же образом, что и производственная конфигурация, но они грамматически отличаются. Ну, я многое узнал о конфиге MockMVC с этой проблемой.
Вот решение, если вы хотите провести модульное тестирование с помощью Spring Mobile.
Первый класс
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebTestConfig.class})
@WebAppConfiguration
public class WebTestConfigAware {
@Autowired
private WebApplicationContext context;
protected MockMvc mockMvc;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
DeviceResolverRequestFilter deviceResolverRequestFilter = new DeviceResolverRequestFilter();
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(this.springSecurityFilterChain, deviceResolverRequestFilter).build();
}
}
Второй класс
@Configuration
@EnableWebMvc
@Import({RootTestConfig.class, WebCommonSecurityConfig.class})
public class WebTestConfig extends WebMvcConfigurerAdapter{
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new ServletWebArgumentResolverAdapter(new DeviceWebArgumentResolver()));
argumentResolvers.add(new SitePreferenceHandlerMethodArgumentResolver());
}
}
и тестовый класс
public class AuthenticationControllerTest extends WebTestConfigAware {
@Test
public void testAuthenticationRequest() throws Exception {
AuthenticationRequestDto authentication = new AuthenticationRequestDto();
authentication.setUsername("admin");
authentication.setPassword("Test1234");
String jsonAuthentication = TestUtil.convertObjectToJsonString(authentication);
ResultActions res = mockMvc.perform(post("/auth")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE).content(jsonAuthentication));
res.andExpect(status().isOk());
}
В вашем тестовом классе вы неправильно строите свой запрос
// a couple of issues here explained below
ResultActions res = mockMvc.perform(post("/auth", authentication, device).contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(authentication)));
post("/auth", authentication, device)
аутентификация и устройство интерпретируются как URI пути, поэтому они здесь не нужны, ваш URI контроллера не имеет переменных URI пути. Если вы намереваетесь передать 2 объекта как тело запроса, вам нужно изменить ваш тестовый запрос и ваш обработчик запросов контроллера. Вы не можете передать 2 объекта как тело запроса, вам нужно заключить оба объекта в один
class AuthenticationRequest {
private AuthenticationRequestDto authenticationDto;
private Device device;
// constructor, getters and setters
}
В вашем контроллере
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> authenticationRequest(@RequestBody AuthenticationRequest request) throws AuthenticationException {
AuthenticationRequestDto authenticationDto = request.getAuthenticationDto();
Device device = request.getDevice();
// ....
}
Также в вашем тесте вам нужно передать строку объекта JSON, вы конвертируете ее в байты (вот почему вы получаете 415):
// note the change in the TestUtils, the method being called is convertObjectToJsonString (you'll need to add it)
ResultActions res = mockMvc.perform(post("/auth").contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonString(new Authenticationrequest(authentication, device))));