Search code examples
javaspringmockitointegration-testingmockmvc

Spring Integration testing with MockMvc - service injection


I'm trying to make an integration test going all the way from the top (controller) down to the repositories (mocked). I'm having issue with getting an actual service (not mock) injected into a controller and mocking the service's repositories. Most examples I've seen either call the endpoint via MockMvc and test the controller that contains all the logic, so no services, or they just mock the service and return a set response which I see no point in testing at all. My classes work as such: Controller contains the service which contains the repository

Currently I have the following test class for that:

@WebMvcTest(PatientRecordController.class)
public class PatientRecordControllerTests {

    @Autowired
    MockMvc mockMvc;

    @Autowired
    ObjectMapper mapper;

    @MockBean
    PatientRecordService patientRecordService;

    @Test
    public void createRecord_WhenDtoValid_CreateRecord() throws Exception {
        PatientRecordDto recordDto = PatientRecordDto.builder()
            .name("John Doe")
            .age(47)
            .address("New York USA")
            .build();

        PatientRecord record = ModelMapperUtil.convertTo(recordDto, PatientRecord.class);
        Mockito.when(patientRecordService.saveRecord(recordDto)).thenReturn(record);

        MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/patient")
            .contentType(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            .content(this.mapper.writeValueAsString(recordDto));

        mockMvc.perform(mockRequest)
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", notNullValue()))
            .andExpect(jsonPath("$.name", is("John Doe")));
    }
}

What I would like to be able to do is something akin to following:

@Autowired
@InjectMocks
private PatientRecordService patientRecordService;

@Mock
private PatientRecordRepository patientRecordRepository;

Theoretically, with this I'd get a bean of PatientRecordService that has PatientRecordRepository mock injected, and then instead of doing

Mockito.when(patientRecordService.saveRecord(recordDto)).thenReturn(record);

I could do

Mockito.when(patientRecordRepository.save(recordDto)).thenReturn(record);

And then the whole logic inside of the service would be tested and only repository response would be mocked. Obviously this is not how it works, so how would I go about in achieving this?


Solution

  • You should be able to

    @WebMvcTest({PatientRecordController.class, PatientRecordService.class})
    
    @MockBean
    private PatientRecordRepository patientRecordRepository;
    
    

    Does that not achieve what you need?