2011-01-12 15 views
26

Ho un attributo di convalida di classe asp.net mvc personalizzato. La mia domanda è: come posso testarlo? Sarebbe una cosa testare che la classe abbia l'attributo ma questo non testerebbe effettivamente la logica al suo interno. Questo è quello che voglio testare.Come posso testare il mio attributo di convalida personalizzato

[Serializable] 
[EligabilityStudentDebtsAttribute(ErrorMessage = "You must answer yes or no to all questions")] 
public class Eligability 
{ 
    [BooleanRequiredToBeTrue(ErrorMessage = "You must agree to the statements listed")] 
    public bool StatementAgree { get; set; } 

    [Required(ErrorMessage = "Please choose an option")] 
    public bool? Income { get; set; } 

..... rimossa per brevità }

[AttributeUsage(AttributeTargets.Class)] 
public class EligabilityStudentDebtsAttribute : ValidationAttribute 
{ 
    // If AnyDebts is true then 
    // StudentDebts must be true or false 

    public override bool IsValid(object value) 
    { 
     Eligability elig = (Eligability)value; 
     bool ok = true; 
     if (elig.AnyDebts == true) 
     { 
      if (elig.StudentDebts == null) 
      { 
       ok = false; 
      } 
     } 
     return ok; 

    } 
} 

Ho cercato di scrivere un test come segue, ma questo non funziona:

[TestMethod] 
public void Eligability_model_StudentDebts_is_required_if_AnyDebts_is_true() 
{ 

    // Arrange 
    var eligability = new Eligability(); 
    var controller = new ApplicationController(); 

    // Act 
    controller.ModelState.Clear(); 
    controller.ValidateModel(eligability); 
    var actionResult = controller.Section2(eligability,null,string.Empty); 

    // Assert 
    Assert.IsInstanceOfType(actionResult, typeof(ViewResult)); 
    Assert.AreEqual(string.Empty, ((ViewResult)actionResult).ViewName); 
    Assert.AreEqual(eligability, ((ViewResult)actionResult).ViewData.Model); 
    Assert.IsFalse(((ViewResult)actionResult).ViewData.ModelState.IsValid); 
} 

Il ModelStateDictionary non lo fa contenere la chiave per questo attributo personalizzato. Contiene solo gli attributi per gli attributi di convalida standard.

Perché è questo?

Qual è il modo migliore per verificare questi attributi personalizzati?

risposta

35

Il tuo attributo EligabilityStudentDebtsAttribute è solo una classe standard, come tutto il resto, basta testare il metodo IsValid(). Se funziona OK, affidarsi a Framework che attributo funzioni OK.

Quindi:

[Test] 
public void AttibuteTest() 
{ 
    // arrange 
    var value = //.. value to test - new Eligability() ; 
    var attrib = new EligabilityStudentDebtsAttribute(); 

    // act 
    var result = attrib.IsValid(value); 

    // assert 
    Assert.That(result, Is.True) 
} 
+0

Doh! Ovviamente! – MightyAtom

+1

È questo il modo migliore per eseguire la convalida della proprietà incrociata? (Convalida del modello che coinvolge più di una proprietà) – MightyAtom

+0

mantienilo semplice .. prova, se lavori per te - nessun motivo per fare più compex test :) –

6

l'attributo di convalida personalizzato potrebbe essere dipendente dallo stato di altre proprietà. In questo caso è possibile utilizzare i metodi statici System.ComponentModel.DataAnnotations.Validator, ad esempio:

var model = ... 
var context = new ValidationContext(model); 
var results = new List<ValidationResult>(); 
var isValid = Validator.TryValidateObject(model, context, results, true); 
Assert.True(isValid); 
+1

potrebbe voler aggiungere il flag true per convalidare tutte le proprietà - "Validator.TryValidateObject (model, context, results, true);" - Ho avuto problemi durante il test della convalida con NUnit, la convalida all'interno di "override protetto ValidationResult IsValid (..)" non è stata colpita a meno che non avessi fornito "validateAllProperties" come true, quindi i test non sono stati eseguiti come previsto e non ho potuto eseguire il debug nel mio codice. – JimiSweden

Problemi correlati