@Test
    public void updateDeviceTelemetryInterval() throws Exception {

        int deviceId = 1;
        String serviceName = "AAAService";

        //given service info
        ServiceDto serviceDto = new ServiceDto();
        serviceDto.setServiceId(1);
        AzureIotHubEntity azureIotHubEntity = new AzureIotHubEntity();
        azureIotHubEntity.setAzureIotHubConnectionString("");
        serviceDto.setAzureIotHub(azureIotHubEntity);
        //given device info
        DeviceDto deviceDto = new DeviceDto();
        deviceDto.setDeviceId(1);
        //given interval info
        Gson gson = new Gson();
        DeviceDto device = new DeviceDto();
        device.setTelemetryInterval(1);
        String str = gson.toJson(device);

        given(serviceService.findServiceByName(serviceName)).willReturn(serviceDto);
        given(deviceService.findDeviceById(deviceId)).willReturn(deviceDto);

        //when then
        MockHttpServletRequestBuilder createUserRequest = post("/ServiceName/setTelemetryInterval/1")
                .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
                .content(str);

        this.mvc.perform(createUserRequest)
                .andExpect(status().is2xxSuccessful());
    }

이와 같은 테스트코드는 정상적 상황을 테스트하는 상황입니다.

 

만약 해당하는 서비스가 없는 상황에서는 다음과 같은 Exception이 발생하도록 내부적으로 정의했습니다.

@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="No such Service")
public class ServiceNotFoundException extends Exception {

    public ServiceNotFoundException(String message){
        super(message);
    }

    public ServiceNotFoundException(String message, Throwable cause) {
        super(message,cause);
    }
}

이와 같은 Exception이 의도한 것처럼 발생하는지 우리는 일반적으로 TestCode에서 아래와 같은 annotation을 통해서 처리합니다.

@Test(expected = ServiceNotFoundException.class)

그런데 여기서 주의해야 할점이 있습니다!!! 

 

우리가 일반적으로 Spring mvc를 사용할때 위와 같은 형태로 Exception을 정의할 경우, 내부적으로 Exception을 catch하여 밖으로 나가지 않도록 하고 HTTP STATUS코드를 변경하게 됩니다.

따라서 위와 같이 @Test(expected) 를 추가하더라도 Exception은 잡히지 않습니다.

어떻게 하면 내가 의도한 Exception을 잡아낼 수 있을지 Spring 내부소스를 살펴보았습니다.

final class TestDispatcherServlet extends DispatcherServlet {

@Override
	protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
			@Nullable Object handler, Exception ex) throws Exception {

		ModelAndView mav = super.processHandlerException(request, response, handler, ex);

		// We got this far, exception was processed..
		DefaultMvcResult mvcResult = getMvcResult(request);
		mvcResult.setResolvedException(ex);
		mvcResult.setModelAndView(mav);

		return mav;
	}
 

위와 같이 result에 resolvedException에 발생한 Exception정보를 저장하고 있습니다.

그렇다면 아래와 같이 테스트 코드를 작성하면 될것이라고 추측됩니다.

@Test
    public void updateDeviceTelemetryIntervalNonExistService() throws Exception {

        //given
        ServiceDto serviceDto = new ServiceDto();

        Gson gson = new Gson();
        DeviceDto device = new DeviceDto();
        device.setTelemetryInterval(1);
        String str = gson.toJson(device);

        given(serviceService.findServiceByName("TestService")).willReturn(serviceDto);

        //when then
        MockHttpServletRequestBuilder createUserRequest = post("/AAAService/setTelemetryInterval/1")
                .contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
                .content(str);

        this.mvc.perform(createUserRequest)
                .andExpect((result)->assertTrue(result.getResolvedException().getClass().isAssignableFrom(ServiceNotFoundException.class)))
                .andExpect(status().is4xxClientError());
    }

테스트 결과 404 NotFound  와 exception의 유형을 모두 확인할 수  있습니다.

+ Recent posts