为啥@WebMvcTest 不将 Controller-Advices 加载到 Application-Context 中?

Posted

技术标签:

【中文标题】为啥@WebMvcTest 不将 Controller-Advices 加载到 Application-Context 中?【英文标题】:Why does @WebMvcTest not load Controller-Advices into the Application-Context?为什么@WebMvcTest 不将 Controller-Advices 加载到 Application-Context 中? 【发布时间】:2022-01-02 02:22:31 【问题描述】:

Hello在我的参数化 junit5-test 中,我得到一个 NestedServletException,直到我添加 @ContextConfiguration-我的测试类上方的注释,我在其中引用了使用@ControllerAdvice 注释的自定义异常处理程序。在其中,对于我想以某种方式处理的所有异常,我都有用 @ExceptionHandler(ExceptionXY.class) 注释的方法。 抛出 NestedServletException 的示例

@ExtendWith(SpringExtension.class)
@WebMvcTest(value = SomeController.class)
@WithMockUser("123@domain.de")
class SomeControllerIntegrationTest 
     
    @ParameterizedTest
    @CsvSource("1000,-100",
                "100,1000000",
                "-8,500",)
    void getInfoForSomething_invalidInputCheck_Status400(int valA, int valB)
            //act
mockMvc.perform(get("v1/anApiEndpoint/"+valA+"/furtherInformation/"+valB+"/getBirthday"))
             .andExpect(status().isBadRequest)
...

抛出异常:org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是 javax.validation.ConstraintViolationException: SomeDto.valA: must be less than or equal to 10

    @ExtendWith(SpringExtension.class)
    @WebMvcTest(value = SomeController.class)
    @ContextConfiguration(classes = SomeExceptionHandler.class, SomeController.class, SomeService.class)
    @WithMockUser("123@domain.de")
    class SomeControllerIntegrationTest 
         
        @ParameterizedTest
        @CsvSource("1000,-100",
                    "100,1000000",
                    "-8,500",)
        void getInfoForSomething_invalidInputCheck_Status400(int valA, int valB)
                //act
    mockMvc.perform(get("v1/anApiEndpoint/"+valA+"/furtherInformation/"+valB+"/getBirthday"))
                 .andExpect(status().isBadRequest)
    ...

不抛出异常,并按预期返回 400。

现在我读到@WebMvcTest 应该添加 ControllerAdvices(在本例中为 SomeExceptionHandler.class),但在我的情况下似乎没有发生。为什么我必须自己配置上下文,有没有办法在没有 ContextConfiguration-Annotation 的情况下做到这一点

更新:自定义异常处理程序位于我在 pom.xml 中添加的另一个启动器中,这可能会导致该错误。

【问题讨论】:

这与您的方法没有什么不同,但如果您不喜欢该注释,您可以使用 MockMvcBuilders .standaloneSetup(SomeController.class) .setControllerAdvice(new SomeExceptionHandler()) @hovanessyan 你能解释一下为什么默认情况下只添加一个控制器建议吗?我发现当我不添加@ContextConfiguration注解时,添加了我的其他Controller Advice。 如何在运行时从其他启动器激活自定义异常处理程序?它是自动配置的还是 @Configuration 类的一部分? 它在@configurationclass @rieckpil 中 【参考方案1】:

使用@WebMvcTest,只有与 MVC 相关的组件才会填充到切片的 Spring 测试上下文中。正如您所提到的,您使用 @Configuration 从不同的启动器激活自定义异常处理程序,默认情况下不会填充,因为 @WebMvcTest 不会查找 @Configuration 类。

您仍然可以使用 @Import(NameOfYourConfig.class) 在测试类顶部手动添加配置,以使用更多 bean 丰富切片的测试上下文。

有关详细信息,请考虑relevant section in the Spring Boot documentation 或此Spring Boot Test slice overview。

【讨论】:

非常感谢。我对导入不会考虑@conditional吗?因此,如果我需要它,我应该使用@ImportAutoConfiguration 不客气。是的,应该是这样。

以上是关于为啥@WebMvcTest 不将 Controller-Advices 加载到 Application-Context 中?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 StandardScaler 不将元数据附加到输出列?

为啥不将 Javascript 事件委托发挥到极致呢?

为啥 execlp() 不将输出打印到终端?

为啥此控件不将结果保存回数据库?

为啥不将值添加到 NSMutableArray?

为啥 Octave 不将变量封装在嵌套函数中?