首页 > 解决方案 > Springboot测试如何将控制器的参数解析为对象

问题描述

我在控制器中有这样的方法签名。当我尝试为它编写单元测试时。它返回 500 而不是 404。看起来它无法将 {id} 转换为 Optional 是否需要进行任何设置才能自动将参数转换为对象?

谢谢

@RequestMapping("/propagationStores")
public class PropagationStoreController {


    private StoreRepository storeRepository;
    private CustomValidator validator;
    public PropagationStoreController(StoreRepository storeRepository) {
        this.storeRepository = storeRepository;

    }

    @GetMapping(value = "/{id}")
    public Resource<StoreDto> getById(@PathVariable("id") Optional<Store> storeOptional) {

        return storeOptional
            .map(StoreConverter::toDto)
            .map(store -> {
                Resource<StoreDto> resource = new Resource<>(store);
                resource.add(new Link("http://localhost").withTitle("localhost"));
                return resource;
        }).orElseThrow(ResourceNotFoundException::new);
    }

当我尝试使用以下代码测试 getById 方法时。我得到 500 而不是 400

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class PropagationStoreControllerIT {


    @MockBean
    StoreRepository storeRepository;
    @MockBean
    CustomValidator customValidator;


    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetById() throws Exception {
        when(storeRepository.findById(1l)).thenReturn(Optional.empty());
        mockMvc.perform(get("/propagationStores/1")).andDo(print()).andExpect(status().is4xxClientError());
    }
}

我期待状态 404,但我得到了 500。

日志如下。

   MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /propagationStores/1
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {}

Handler:
             Type = local.tux.propagation.controller.PropagationStoreController
           Method = public org.springframework.hateoas.Resource<local.tux.propagation.dto.Store$StoreDto> local.tux.propagation.controller.PropagationStoreController.getById(java.util.Optional<local.tux.propagation.evaluator.domain.Store>)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 500
    Error message = null
          Headers = []
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /propagationStores/1
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {}

Handler:
             Type = local.tux.propagation.controller.PropagationStoreController
           Method = public org.springframework.hateoas.Resource<local.tux.propagation.dto.Store$StoreDto> local.tux.propagation.controller.PropagationStoreController.getById(java.util.Optional<local.tux.propagation.evaluator.domain.Store>)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 500
    Error message = null
          Headers = []
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

java.lang.AssertionError: Range for response status value 500 
Expected :CLIENT_ERROR
Actual   :SERVER_ERROR

标签: javaspring-bootspring-boot-test

解决方案


Define your controller method as:

public Resource<StoreDto> getById(@PathVariable("id") Optional<String> id) {
    ......
}

id can be converted to a string or a number, not into a Store class.


推荐阅读