简体   繁体   中英

Unit testing spring rest controller error handling

I have a spring rest controller as detailed below

@RestController
@RequestMapping(value = "/data")
public class DataController {

private final IDataService service;
private static final Logger LOG = Logger.getLogger(DataController.class);

/**
 * The Constructor.
 *
 * @param service
 *            the service
 */
@Autowired
public DataController(final IDataService service) {
    this.service = service;
}

// Country
/**
 * Find all countries.
 *
 * @return the response entity< list< country>>
 */
@RequestMapping(value = "/country", produces = Util.APPLICATION_JSON_UTF8_STRING, method = RequestMethod.GET)
public ResponseEntity<List<Country>> findAllCountries() {
    List<Country> countries = new ArrayList<>();
    try {
        countries = this.service.findAllCountries();
        return new ResponseEntity<>(countries, null, HttpStatus.OK);
    } catch (final Exception e) {
        LOG.error(e.getMessage(), e);
        return new ResponseEntity<>(countries, null, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

I have a unit test using Mockito and Mock Mvc which tests the successful path

public class DataControllerTest implements IAbstractController {

private MockMvc mockMvc;

@Mock
private IDataService serviceMock;

@InjectMocks
private DataController dataController;

@Autowired
WebApplicationContext wac;

/**
 * Sets the up.
 *
 * @throws Exception
 *             the exception
 */
@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
    this.mockMvc = MockMvcBuilders.standaloneSetup(this.dataController).build();
}

 @Test
public void testFindAllCountries() throws Exception {

    final Country first = new CountryBuilder().id(3L).name("USA").regionId(1L).active(true).build();
    final Country second = new CountryBuilder().id(66L).name("India").regionId(2L).active(true).build();
    final Country third = new CountryBuilder().id(1L).name("United Kingdom").regionId(4L).active(true).build();

    when(this.serviceMock.findAllCountries()).thenReturn(Arrays.asList(first, second, third));

    final ResultActions ra = this.mockMvc.perform(get("/data/country.do")).andExpect(status().isOk())
        .andExpect(content().contentType(Util.APPLICATION_JSON_UTF8)).andExpect(jsonPath("$", hasSize(3)))
        .andExpect(jsonPath("$[0].id", is(3))).andExpect(jsonPath("$[0].name", is("USA")))
        .andExpect(jsonPath("$[0].regionId", is(1))).andExpect(jsonPath("$[0].active", is(true)))
        .andExpect(jsonPath("$[1].id", is(66))).andExpect(jsonPath("$[1].name", is("India")))
        .andExpect(jsonPath("$[1].regionId", is(2))).andExpect(jsonPath("$[1].active", is(true)))
        .andExpect(jsonPath("$[2].id", is(1))).andExpect(jsonPath("$[2].name", is("United Kingdom")))
        .andExpect(jsonPath("$[2].regionId", is(4))).andExpect(jsonPath("$[2].active", is(true)));

    Assert.assertNotNull(ra);
    verify(this.serviceMock, times(1)).findAllCountries();
    verifyNoMoreInteractions(this.serviceMock);

}

However, I am struggling to test the catch block where an error response is returned. What are the best practices around this? Can anyone advise?

FYI the Abstract controller just contains annotations

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public interface IAbstractController {

}

So the test I am trying is

@Test(expected = Exception.class)
public void testFindAllCountriesThrowsException() throws Exception {
    Mockito.doThrow(new RuntimeException()).when(this.serviceMock.findAllCountries());
    this.mockMvc.perform(get("/data/country.do"));
}

Whilst this test passes, accorrding to the coverage infor from EclEmma, my catch block is still not being covered by the test

In your test, try using

Mockito.doThrow(new RuntimeException()).when(this.serviceMock).findAllCountries());

If you encounter a compile error, you might also use

when(this.serviceMock.findAllCountries()).thenThrow(new RuntimeException());

you have to get a error message in terms of error handling

MvcResult mvcResult = resultActions.andExpect(status().isForbidden()).andReturn();
String errMsg = mvcResult.getResponse().getErrorMessage();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM