我的@ControllerAdvice
带注释的控制器如下所示:
@ControllerAdvice
public class GlobalControllerExceptionHandler {
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
@ExceptionHandler(AuthenticationException.class)
public void authenticationExceptionHandler() {
}
}
当然我的开发是测试驱动的,我想在JUnit测试中使用我的异常处理程序。我的测试案例如下:
public class ClientQueriesControllerTest {
private MockMvc mockMvc;
@InjectMocks
private ClientQueriesController controller;
@Mock
private AuthenticationService authenticationService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void findAllAccountRelatedClientsUnauthorized() throws Exception {
when(authenticationService.validateAuthorization(anyString())).thenThrow(AuthenticationException.class);
mockMvc.perform(get("/rest/clients").header("Authorization", UUID.randomUUID().toString()))
.andExpect(status().isUnauthorized());
}
}
我可能需要注册ControllerAdvice
班级。怎么做?
答案 0 :(得分:26)
从Spring 4.2开始,您可以将ControllerAdvice直接注册到StandaloneMockMvcBuilder中:
MockMvcBuilders
.standaloneSetup(myController)
.setControllerAdvice(new MyontrollerAdvice())
.build();
答案 1 :(得分:21)
为了激活完整的Spring MVC配置,您需要使用MockMvcBuilders.webAppContextSetup
而不是MockMvcBuilders.standaloneSetup
。
查看Spring文档的this部分以获取更多详细信息。
您的代码如下:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("test-config.xml")
public class ClientQueriesControllerTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private AuthenticationService authenticationService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void findAllAccountRelatedClientsUnauthorized() throws Exception {
when(authenticationService.validateAuthorization(anyString())).thenThrow(AuthenticationException.class);
mockMvc.perform(get("/rest/clients").header("Authorization", UUID.randomUUID().toString()))
.andExpect(status().isUnauthorized());
}
}
然后在test-config.xml
内,你会为AuthenticationService
添加一个模拟的Spring bean。
<bean id="authenticationService" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="your.package.structure.AuthenticationService"/>
</bean>
如果要重用常规的Spring配置文件而不是创建AuthenticationService
,您当然可以使用配置文件在测试中注入模拟test-config.xml
。
<强>更新强>
经过深入挖掘后,我发现(StandaloneMockMvcBuilder
)返回的MockMvcBuilders.standaloneSetup
完全可以自定义。这意味着您可以插入您喜欢的任何异常解析器。
但是,由于您使用的是@ControllerAdvice
,因此以下代码无效。
但是,如果您的@ExceptionHandler
方法位于同一个控制器中,则您需要更改的代码如下:
mockMvc = MockMvcBuilders.standaloneSetup(controller).setHandlerExceptionResolvers(new ExceptionHandlerExceptionResolver()).build();
更新2
当你还使用@ControllerAdvice
时,还有一些挖掘给出了如何注册正确的异常处理程序的答案。
您需要将测试中的设置代码更新为以下内容:
@Before
public void setUp() throws Exception {
final ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver();
//here we need to setup a dummy application context that only registers the GlobalControllerExceptionHandler
final StaticApplicationContext applicationContext = new StaticApplicationContext();
applicationContext.registerBeanDefinition("advice", new RootBeanDefinition(GlobalControllerExceptionHandler.class, null, null));
//set the application context of the resolver to the dummy application context we just created
exceptionHandlerExceptionResolver.setApplicationContext(applicationContext);
//needed in order to force the exception resolver to update it's internal caches
exceptionHandlerExceptionResolver.afterPropertiesSet();
mockMvc = MockMvcBuilders.standaloneSetup(controller).setHandlerExceptionResolvers(exceptionHandlerExceptionResolver).build();
}
答案 2 :(得分:19)
使用以下解决方案超越NestedServletException ...
final StaticApplicationContext applicationContext = new StaticApplicationContext();
applicationContext.registerSingleton("exceptionHandler", GlobalControllerExceptionHandler.class);
final WebMvcConfigurationSupport webMvcConfigurationSupport = new WebMvcConfigurationSupport();
webMvcConfigurationSupport.setApplicationContext(applicationContext);
mockMvc = MockMvcBuilders.standaloneSetup(controller).
setHandlerExceptionResolvers(webMvcConfigurationSupport.handlerExceptionResolver()).
build();
答案 3 :(得分:0)
如果您有多个建议类,每个建议类都带有@ExceptionHandler
,并且其中一个类正在处理非常通用的基本异常,例如@ExceptionHandler({Exception.class})
,那么您将需要在建议类中添加一些优先顺序按照这个答案
答案 4 :(得分:-1)
您可以将其添加到测试类
@Autowired
@Qualifier("handlerExceptionResolver")
void setExceptionResolver(HandlerExceptionResolver resolver)
{
this.exceptionResolver = resolver;
}
然后将exceptionResolver
添加到您的MockMvc
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setHandlerExceptionResolvers(this.exceptionResolver).build();
}