2016-11-16 80 views
1

我正在使用Spring微服務(模塊)處理項目,並且我想使用MockMvc來測試我的REST端點。我的測試適用於請求有效的情況,但在請求無效的url時不起作用。通過不工作,我的意思是我的自定義異常處理程序(@ControllerAdvice)沒有被調用,引發異常並且測試失敗。使用自定義異常處理測試REST端點

我的異常處理程序和測試類在不同的模塊中實現。

共模塊(的ExceptionHandler)

@ControllerAdvice 
public class CoreExceptionHandler { 

    @ExceptionHandler(value = Exception.class) 
    public ResponseEntity<ErrorMessageDTO> handleException(Exception ex, HttpServletRequest request) { 

     // Getting servlet request URL 
     String uri = request.getRequestURI(); 
     HttpStatus a; 

     ErrorMessageDTO errorMessage; 

     if (ex instanceof CoreException) { 
      CoreException e = (CoreException) ex; 
      ... 
      errorMessage = new ErrorMessageDTO(e, uri); 
     } else { 
      errorMessage = new ErrorMessageDTO(ex, uri); 
      ... 
     } 
     return new ResponseEntity<ErrorMessageDTO>(errorMessage, a); 
    } 
} 

國家模塊

這是我的REST端點和測試類的貫徹落實。通用模塊依賴包含在這個模塊的pom.xml中,包通過主類進行掃描。

CountryApplication.java

@EnableCaching 
@EnableDiscoveryClient 
@EnableAspectJAutoProxy 
@SpringBootApplication(scanBasePackages = { 
    "com.something1.something2.something3.common.exception", 
    "com.something1.something2.something3.common.util.logged", 
    "com.something1.something2.something3.country" 
}) 
public class CountryApplication { 
    public static void main(String[] args) throws Exception { 
     SpringApplication.run(CountryApplication.class, args); 
    } 
    ... 
} 

CountryService.java

這是我的服務類中的方法。

@GetMapping("/{id:\\d+}") 
public CountryDTO getCountryById(@PathVariable("id") Integer id) throws CoreException { 

    Country countryEntity = this.countryRepository.findOne(id); 

    // requesting for id that does not exist 
    if (countryEntity == null) { 
     throw new CoreException(CoreError.ENTITY_NOT_FOUND); 
    } 
    return this.countryMapper.daoToDto(countryEntity); 
} 

CountryServiceTest.java

@SpringBootTest 
@AutoConfigureMockMvc 
@AutoConfigureTestDatabase 
@RunWith(SpringRunner.class) 
public class CountryServiceTest { 
    ... 
    @Autowired 
    private MockMvc mockMvc; 

    @Test 
    public void getByIdTest() throws Exception { 

     // Get by id exists 
     mockMvc.perform(get("/2")) 
      .andExpect(status().isOk()) 
      .andExpect(content().contentType(contentType)) 
      .andDo(print()); 

     // Get by id not exists. NOT WORKING 
      mockMvc.perform(get("/100000")) 
      .andExpect(status().isNotFound()) 
      .andExpect(content().contentType(contentType)); 

    } 
} 

正如我如上所述,問題是,在試驗方法的第二請求,所述CoreExceptionHandler不會被調用和測試失敗投擲:

NestedServletException: Request processing failed; nested exception is com.something1.something2.something3.common.exception.CoreException

通用模塊的依賴性配置良好(至少當我在非測試模式下進行部署時),因爲我也將其用於其他事情,並且在我未測試時會調用ExceptionHandler。

另一個奇怪的是,當我部署我的測試時,Spring Boot的日誌顯示CoreExceptionHandler被檢測到。這是線。Detected @ExceptionHandler methods in coreExceptionHandler

回答

0

有兩個問題下面所解釋:

(1) ControllerAdvice沒有爲MockMvc對象在CountryServiceTest類設置,這是可以做到,如下所示:

MockMvc mockMvc = standaloneSetup(yourController) 
     .setHandlerExceptionResolvers(new CoreExceptionHandler()) 
     .build(); 

(2)由於CoreException由Spring Container封裝爲NestedServletException,因此需要使用exception.getCause()來檢查您的異常,如下所示:

@ControllerAdvice 
    public class CoreExceptionHandler { 

     @ExceptionHandler(value = Exception.class) 
     public ResponseEntity<ErrorMessageDTO> handleException(Exception ex, 
      HttpServletRequest request) { 

      // Getting servlet request URL 
      String uri = request.getRequestURI(); 
      HttpStatus a; 

      ErrorMessageDTO errorMessage; 

      //check with exception cause 
      if (ex.getCause() instanceof CoreException) { 
       CoreException e = (CoreException) ex; 
       ... 
       errorMessage = new ErrorMessageDTO(e, uri); 
      } else if (ex instanceof CoreException) { 
       //this block will be used only when direct CoreException triggered 
       CoreException e = (CoreException) ex; 
       ... 
       errorMessage = new ErrorMessageDTO(e, uri); 
      } else { 
       errorMessage = new ErrorMessageDTO(ex, uri); 
       ... 
      } 
      return new ResponseEntity<ErrorMessageDTO>(errorMessage, a); 
     } 
    } 

另外,我建議不要在處理一個通用方法所有的異常,這將是非常困難的支持/維護,而不是分裂的CoreExceptionHandler使用多個@ExceptionHandler方法/類。

+0

正如我所提到的,測試時''handleException'方法根本不會被調用。 – pirox22

+0

我從'MockMvc'中刪除了'@ Autowired',並按照@ @ Before'方法中的建議初始化它。我仍然得到相同的錯誤,處理程序仍然沒有被調用。 – pirox22