Как настроить 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))));
Другие вопросы по тегам