当@PathVariable是一个字符串时,Spring控制器测试失败,404

时间:2018-03-07 12:19:16

标签: java spring unit-testing mockito

我正在尝试测试一个Spring控制器方法 - 该方法位于帖子的末尾,下面是测试类。我把它剥了一下试图缩小问题的范围。

当我按原样运行测试时失败:

java.lang.AssertionError: Status 
Expected :200
Actual   :404

如果我按如下方式编辑mockMvc.perform然后测试通过,我甚至不必将控制器中的@PathVariables更改为Longs:

mockMvc.perform(get(ApplicationEndPoints.GET_CCS_NAME_AND_ADDRESS_AJAX, 1L, 2L))
       .andExpect(status().isOk());

控制器方法本身工作正常并按预期返回JSON。我可以只使用这些Long值并期望测试正常或如何让它与字符串一起使用?

我应该补充一点,我是一个完全测试的菜鸟。谢谢!

控制器方法:

@PreAuthorize("hasAuthority('auditor')")
@RequestMapping(value = ApplicationEndPoints.GET_APPLICANT_DATA, method = RequestMethod.GET)
@ResponseBody
public ApplicantData getNameAndAddress(@PathVariable("businessId") String businessId, @PathVariable("date") String date) {
    //Date d = Date.valueOf(date);
    ApplicantParams params = new ApplicantParams();
    //params.setBusinessId(businessId);
    //params.setApplicationReceivedDate(d);
    params.setRoleId(ADDRESS_ROLE.HR.getRoleId());
    return applicantService.getApplicantData(params);
 }

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationTestConfig.class})
@WebAppConfiguration
public class ClientDetailAjaxControllerTest {

    @InjectMocks
    private ClientDetailAjaxController clientDetailAjaxController;
    private MockMvc mockMvc;
    private ApplicantServiceInterface<Applicant> applicantService = Mockito.mock(ApplicantServiceImpl.class, Mockito.RETURNS_DEEP_STUBS);

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(clientDetailAjaxController).build();
    }


    @Test
    public void getNameAndAddress() throws Exception { 
        Mockito.when(applicantService.getApplicantData(Mockito.any(ApplicantParams.class)))
               .thenReturn(ApplicationTestData.getApplicantData());
        mockMvc.perform(get(ApplicationEndPoints.GET_APPLICANT_DATA, Mockito.anyString(), Mockito.anyString()))
               .andExpect(status().isOk());
        Mockito.verify(applicantService, Mockito.times(1)).getApplicantData(Mockito.any(ApplicantParams.class));
        Mockito.verifyNoMoreInteractions(applicantService);
    }

}
编辑:为了回应评论,我已经清理了一两件事......

1 个答案:

答案 0 :(得分:2)

404告诉您mockMVC无法匹配您尝试调用的控制器方法。

我注意到在您的控制器中,路径为ApplicationEndPoints.GET_APPLICANT_DATA,而在测试中,您显示路径为ApplicationEndPoints.GET_CCS_NAME_AND_ADDRESS_AJAX

尽管如此 - 请勿使用Mockito.anyString()代替您必须在mockMVC RequestBuilder方法中提供给perform的参数值。

以下是代码应该如何显示的概念(从您的示例中派生出来):

测试此控制器方法:

@RequestMapping(value = "/applicant/name-and-address/", method = RequestMethod.GET)
public ApplicantData getNameAndAddress(@PathVariable("businessId") String businessId, @PathVariable("date") String date) {
    // some code
 }

您需要执行以下操作:

mockMvc.perform(get("/applicant/name-and-address/{businessId}/{date}", "myBusinessId", "myDateAsString")).andExpect(status().isOk());

不同之处在于你必须传递实际的字符串值,而不是Mockito.anyString()。

其他一些说明:

  • 如果您的网址路径变量与您绑定的参数具有相同的名称,则可以写@PathVariable String id,而不是@PathVariable("id") String id

  • 您可以使用@GetMapping代替@RequestMapping GET方法,@PostMapping代替POST等。