当前位置: 首页 > 知识库问答 >
问题:

使用Autowired spring服务测试定制验证器

姜森
2023-03-14

我为我的实体定制了一个Hibernate验证器。我的一个验证器使用自动连线的Spring@Repository。应用程序运行良好,我的存储库在我的验证器上自动连接成功。

问题是我找不到测试验证器的方法,因为我不能将我的存储库注入其中。

Person.class:

@Entity
@Table(schema = "dbo", name = "Person")
@PersonNameMustBeUnique
public class Person {

    @Id
    @GeneratedValue
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @Column()
    @NotBlank()
    private String name;

    //getters and setters
    //...
}

人名必须是唯一的。班

@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = { PersonNameMustBeUniqueValidator.class })
@Documented
public @interface PersonNameMustBeUnique{
    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends javax.validation.Payload>[] payload() default {};
}

验证器:

public class PersonNameMustBeUniqueValidatorimplements ConstraintValidator<PersonNameMustBeUnique, Person> {

    @Autowired
    private PersonRepository repository;

    @Override
    public void initialize(PersonNameMustBeUnique constraintAnnotation) { }

    @Override
    public boolean isValid(Person entidade, ConstraintValidatorContext context) {
        if ( entidade == null ) {
            return true;
        }

        context.disableDefaultConstraintViolation();

        boolean isValid = nameMustBeUnique(entidade, context);

        return isValid;
    }

    private boolean nameMustBeUnique(Person entidade, ConstraintValidatorContext context) {
        //CALL REPOSITORY TO CHECK IF THE NAME IS UNIQUE 
        //ADD errors if not unique...
    }
}

上下文文件有一个验证程序bean:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

再次,它工作正常,但我不知道如何测试它。

我的测试文件是:

@RunWith(MockitoJUnitRunner.class)
public class PersonTest {

    Person e;
    static Validator validator;

    @BeforeClass
    public static void setUpClass() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Test
    public void name__must_not_be_null() {
        e = new Person();
        e.setName(null);
        Set<ConstraintViolation<Person>> violations = validator.validate(e);
        assertViolacao(violations, "name", "Name must not be null");
    }

}

共有3个答案

陶沛
2023-03-14

您可以在测试中将以下bean添加到Spring上下文中:

@RunWith(SpringRunner.class)
@Import(LocalValidatorFactoryBean.class)
public class PersonTest {

  @Autowired
  private Validator validator;

  {
    validator.validate(new Person());
  }

  ...
}
劳豪
2023-03-14

在@BeforeClass上:

@BeforeClass
    public static void setUpClass() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

在测试中,你需要用模拟的bean替换bean:

myValidator.initialize(null);
BeanValidatorTestUtils.replaceValidatorInContext(validator, usuarioValidoValidator, e);

发挥所有魔力的班级:

public class BeanValidatorTestUtils {

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <A extends Annotation, E> void replaceValidatorInContext(Validator validator,
                                                                            final ConstraintValidator<A, ?> validatorInstance,
                                                                                E instanceToBeValidated) {
        final Class<A> anotacaoDoValidador = (Class<A>)
                                                ((ParameterizedType) validatorInstance.getClass().getGenericInterfaces()[0])
                                                    .getActualTypeArguments()[0];

        ValidationContextBuilder valCtxBuilder = ReflectionTestUtils.<ValidationContextBuilder>invokeMethod(validator,
                                                                                                "getValidationContext");
        ValidationContext<E> validationContext = valCtxBuilder.forValidate(instanceToBeValidated);
        ConstraintValidatorManager constraintValidatorManager = validationContext.getConstraintValidatorManager();

        final ConcurrentHashMap nonSpyHashMap = new ConcurrentHashMap();
        ConcurrentHashMap spyHashMap = spy(nonSpyHashMap);
        doAnswer(new Answer<Object>() {
            @Override public Object answer(InvocationOnMock invocation) throws Throwable {
                Object key = invocation.getArguments()[0];
                Object keyAnnotation = ReflectionTestUtils.getField(key, "annotation");
                if (anotacaoDoValidador.isInstance(keyAnnotation)) {
                    return validatorInstance;
                }
                return nonSpyHashMap.get(key);
            }
        }).when(spyHashMap).get(any());

        ReflectionTestUtils.setField(constraintValidatorManager, "constraintValidatorCache", spyHashMap);
    }

}
琴俊良
2023-03-14

我面临着非常相似的问题:如何编写自定义验证器的纯单元测试,其中包含自动配置bean?

我可以通过遵循代码来解决它(受用户abhishekrvce回答的启发)。

这是对带有@Autowired configuration bean的定制验证器的纯单元测试,它从配置文件中读取数据(未在代码中显示)。

@Import({MyValidator.class})
@ContextConfiguration(classes = MyConfiguration.class, initializers = ConfigFileApplicationContextInitializer.class)
class MyValidatorTest {

  private LocalValidatorFactoryBean validator;

  @Autowired
  private ConfigurableApplicationContext applicationContext;

  @BeforeEach
  void initialize() {
    SpringConstraintValidatorFactory springConstraintValidatorFactory
        = new SpringConstraintValidatorFactory(
        applicationContext.getAutowireCapableBeanFactory());
    validator = new LocalValidatorFactoryBean();
    validator.setConstraintValidatorFactory(springConstraintValidatorFactory);
    validator.setApplicationContext(applicationContext);
    validator.afterPropertiesSet();
  }

  @Test
  void isValid()
  {
    Set<ConstraintViolation<MyObject>> constraintViolations = validator
        .validate(myObjectInstance);
    assertThat(constraintViolations).hasSize(1);
  }

}
 类似资料:
  • 我想测试一个WSO2身份提供程序,实际上是它用OpenID配置的联合IdP,我计划使用TraSpeed工具对其进行测试。我正在WEB-INF配置中编辑travelocity.properties文件,将起始参数设置为以下值: 在Tomcat7服务器中声明映像时,它接受新的服务器配置,但代码仍将SAML身份验证激活为主要SSO机制,抛出错误: 是否可以仅使用OpenID堆栈在该Web工具中停用SAM

  • 我正在努力设置ssl来保护我的endpoint。我从我的组织中获得了一份考试证书 我收到一个. pfx文件 我把它转换成. pem----- 我们有基本的基础设施来解决这个问题。jks文件位于一个名为ssl的文件夹中,只需使用confg文件即可获取。 接下来我让杰米来测试这个。遵循步骤 设置一个测试记录器-- 2.将协议更改为https--- 我曾尝试在互联网上搜索和StackFlow有关测试SS

  • 我已经发送了一个soap服务,我必须发送基本的身份验证(用户名和密码)以及qaf中的请求和头值。我尝试在应用程序中添加用户名和密码。属性文件,但服务引发内部服务器错误。请指导我怎么做。

  • 我正在使用带有React-Test-Library的jest来测试一个具有自定义prop-types验证器的组件。验证器如下所示: 我的测试看起来是这样的: 当呈现错误的时,验证器按预期工作。我在控制台中得到以下错误: 但在运行上述测试时,我在终端中得到这样的消息: 我错过了什么?

  • 使用用户证书验证 SSH (服务端) 在以安全为前提下要保障可靠性、可控性和一致性是非常复杂的。我们可以利用 SSH 又或者说 OpenSSH 来替代所依赖的中央身份验证(比如 LDAP 或者 Kerberos) 除了 通过 PIV 和 PKCS#11 验证 SSH 之外,还可以增加远程 SSH 验证的安全性。Facebook 和 Yahoo 已经更换使用 SSH 用户证书来避免中心认证系统宕机。

  • 在我的应用程序中,我有很多REST服务。我已经编写了所有服务的测试: REST服务调用(例如)如下所示: 然后我检查了响应体-一切正常。缺点是,必须启动应用程序才能调用REST服务。 我现在的问题是如何在我的JUnit-@Test方法中做到这一点?它是一个Spring Boot应用程序(带有嵌入式tomcat)。 谢谢帮忙!