2015-02-27 26 views
5

Ho un "AllowedValuesValidator.java" class:Come testare un validatore che implementa ConstraintValidator in java?

public class AllowedValuesValidator implements ConstraintValidator<AllowedValues, String> { 

    String[] values; 
    String defaultValue; 

    @Override 
    public void initialize(AllowedValues constraintAnnotation) { 
     values = constraintAnnotation.allowedValues(); 
     defaultValue = constraintAnnotation.defaultValue(); 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     if (!StringUtils.isEmpty(defaultValue) && StringUtils.isEmpty(value)) { 
      value = defaultValue; 
     } 

     if (!StringUtils.isEmpty(value) && !Arrays.asList(values).contains(value)) { 
      return false; 
     } 
     return true; 
    } 
} 

E la classe corrispondente interfaccia:

@Target(ElementType.FIELD) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy = AllowedValuesValidator.class) 
public @interface AllowedValues { 

    String message(); 

    String fieldName(); 

    int fieldNumber(); 

    String[] allowedValues() default {"Y", "N"}; 

    String defaultValue() default ""; 
} 

voglio essere in grado di scrivere una classe unit test per verificare la logica diretta in quel validatore. Ma sembra che la maggior parte dei luoghi Googled forniscono esempi di classi di test dove abbiamo praticamente testare tutti i validatori per una data classe modello, ad esempio:

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

    @Test 
    public void testEmailExistsIncorrect() { 

     Set<constraintviolation<usercredentialsdto>> violations = validator 
       .validate(credentials, UserCredentialsDto.class); 
     Assert.assertEquals(1, violations.size()); 
    } 

Non voglio costruire modelli finte per testare tutti i validatori. Esiste un modo per creare una classe di test separata per testare la logica in un singolo validatore direttamente senza utilizzare altre classi di modelli ecc.?

+0

In realtà mi sono creato una piccola classe di simulazione all'interno della classe di test e la convalida delle proprietà in quella classe sembra essere abbastanza semplice, quindi funzionerà bene per me. – goe

risposta

5

È possibile verificare il validatore standalone. Lo sfregamento è ovviamente il metodo di inizializzazione, poiché richiede un'istanza dell'annotazione. Fondamentalmente hai tre opzioni:

  1. Aggiungi un secondo metodo di inizializzazione che prende direttamente i parametri richiesti. È quindi possibile utilizzare questo metodo per inizializzare il validatore. È inoltre possibile rendere questo metodo solo pacchetto visibile, purché il test risieda nello stesso pacchetto
  2. Inserire l'annotazione di prova da qualche parte nella classe di test e recuperarla tramite riflessione per passarla al metodo di inizializzazione.
  3. Utilizzare i proxy di annotazione. Questo è anche ciò che Hibernate Validator stesso usa internamente nel caso in cui i vincoli siano configurati via XML o necessari per i test. Esistono due classi in Hibernate Validator che è possibile utilizzare AnnotationDescriptor e AnnotationFactory. Il codice sarebbe un po 'come questo:

-

private AllowedValues createAnnotation(String[]values, String defaultValue) { 
    AnnotationDescriptor<AllowedValues> descriptor = new AnnotationDescriptor<AllowedValues>(AllowedValues.class); 
    descriptor.setValue("values", values); 
    descriptor.setValue("defaultValue", defaultValue); 

    return AnnotationFactory.create(descriptor); 
} 

si avrebbe bisogno di dipendere da classi interne Hibernate Validator, ma a scopo di test questo dovrebbe andare bene. Ovviamente potresti anche creare il tuo framework proxy.