2

I am trying to test a Spring controller method - the method is at the end of the post and the test class below that. I've stripped it back a bit to try and narrow down the problem.

When I run the test as is it fails:

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

If I edit the mockMvc.perform as follows then the test passes, I don't even have to change the @PathVariables in the controller to be Longs:

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

The controller method itself works fine and returns JSON as expected. Can I just use these Long values and expect the test to be ok or how can I get it to work with Strings?

I should add that I'm a total testing noob. Thanks!

controller method:

@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);
 }

test class:

@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);
    }

}

EDIT: I have cleared up one or two things in response to comments...

Shane
  • 305
  • 6
  • 16
  • check this question: https://stackoverflow.com/questions/19803731/spring-mvc-pathvariable – M2E67 Mar 07 '18 at 13:02
  • also this : https://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc-ann-requestmapping-uri-templates – M2E67 Mar 07 '18 at 13:03

1 Answers1

5

404 tells you that mockMVC cannot match the controller method you're trying to call.

I'm noticing that in your controller, the path is ApplicationEndPoints.GET_APPLICANT_DATA, while in the test you've shown the path is ApplicationEndPoints.GET_CCS_NAME_AND_ADDRESS_AJAX.

Nevertheless - don't use Mockito.anyString() in place of parameter values you have to supply to your RequestBuilder in the mockMVC perform method.

Here's an idea how code should look like (derived from your example):

To test this controller method:

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

You need to do something like:

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

The difference is that you have to pass actual string values, not Mockito.anyString().

Some other notes:

  • If your URL path variable has the same name as the parameter you're binding it to, you can write @PathVariable String id, instead of @PathVariable("id") String id.

  • you can use @GetMapping in place of @RequestMapping for GET method, @PostMapping for POST etc.

hovanessyan
  • 30,580
  • 6
  • 55
  • 83