【问题标题】:Spring 5 MVC test custom validatorSpring 5 MVC 测试自定义验证器
【发布时间】:2020-10-19 11:46:10
【问题描述】:

我有使用服务的自定义验证器

public class ProductCodeValidator implements ConstraintValidator<ProdutCode, Set<String>> {

    ...
    @Override
    public boolean isValid(Set<String> pkdCodes, ConstraintValidatorContext context) {
        return pkdCodes != null && service.count(pkdCodes) == pkdCodes.size();
    }

我的目标是在控制器 MVC 测试中使用它,通过模拟服务来控制验证输出。

为了在控制器请求中测试它,我尝试使用@WebMvcTest。但随后安全性突然出现,到处给我 403。为了禁用它,我添加了:

@AutoConfigureMockMvc(addFilters = false) // to avoid security
@WebMvcTest(ProdutDataController.class)
class EditCompanyRegistryDataControllerTest {

    @MockBean
    private ProductService pkdService;
 
    @Autowired
    private MockMvc mvc;

但现在 Spring 也忽略了表单验证,在应该触发验证时返回状态 200/201 而不是 400。

问题:

1 有没有办法只禁用安全性,而无需在 MVC 测试中进行验证?

2 是否可以使用 MockMvcBuilders.standaloneSetup(...) 构建器注册自定义验证器?这样我就可以忽略 spring 上下文,而专注于使用 mocks 进行独立设置。

【问题讨论】:

    标签: spring-mvc spring-security spring-test spring-validator


    【解决方案1】:

    使用 Spring Security 测试支持

    确实没有一个好的方法来禁用 Spring Security,因为不推荐这样做。相反,建议使用 Spring Security 的MockMvc test support。这可确保您的测试与您的配置保持一致。

    使用 Spring Boot,与 Spring Security 的集成会自动添加到 @Autowired MockMvc 实例中。然后您可以选择使用AnnotationsRequestProcessor 来运行您的测试。

    使用注解:

    @Test
    @WithMockUser
    public void requestProtectedUrlWithUser() throws Exception {
        mvc
            .perform(get("/"))
            ...
    }
    

    这将以用户名“user”和角色“ROLE_USER”的用户身份运行。您还可以使用以下内容覆盖属性:@WithMockUser(username="rob", roles="ADMIN")

    或者,您也可以使用RequestPostProcessor

    mvc
        .perform(get("/").with(user("user")))
    

    您还可以覆盖默认角色和密码:

    mvc
        .perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
    

    有关更多详细信息,包括其他自定义、最佳实践等,请参阅我提供的链接。

    独立设置

    独立设置不会自动配置任何内容(包括验证和安全性)。您可以显式配置验证器,但您必须确保它与您的应用程序中配置的实例相同。

    执行此操作的一种方法是 @Autowire Validator 实例。

    @SpringBootTest
    class TheTest {
    
        @Autowired
        Validator validator;
    
        @Test
        void standaloneTest() {
            MockMvc mvc = MockMvcBuilders
                    .standaloneSetup(new MyController())
                    .setValidator(this.validator).build();
        }
    

    或者,您可以直接创建自己的Validator 实例。这使事情变得复杂,因为您必须与您在 Spring 中创建 Validator 的方式保持同步。默认使用OptionalValidatorFactoryBean

    MockMvc mvc = MockMvcBuilders
                .standaloneSetup(new MyController())
                .setValidator(new OptionalValidatorFactoryBean())
                .build();
    

    【讨论】:

    • 自定义验证器不必实现 validate 方法。尝试使用继承 ConstraintValidation 的验证类将失败。我仍在努力尝试在我的测试中使用我的自定义验证器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 2014-11-15
    • 1970-01-01
    • 2019-04-21
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多