2010-01-02 1 views
21

ho scritto modello personalizzato legante in progetto, che utilizza ASP.NET MVC 2. Questo modello legante si legano solo 2 campi del modello:Unità modello di test personalizzato legante in ASP.NET MVC 2

public class TaskFormBinder : DefaultModelBinder 
{ 
    protected override void BindProperty(ControllerContext controllerContext, 
     ModelBindingContext bindingContext, 
     PropertyDescriptor propertyDescriptor) 
    {   
     if (propertyDescriptor.Name == "Type") 
     { 
      var value = bindingContext.ValueProvider.GetValue("Type"); 
      var typeId = value.ConvertTo(typeof(int)); 
      TaskType foundedType; 
      using (var nhSession = Domain.GetSession()) 
      { 
       foundedType = nhSession.Get<TaskType>(typeId); 
      } 
      if (foundedType != null) 
      { 
       SetProperty(controllerContext, bindingContext, propertyDescriptor, foundedType); 
      } 
      else 
      { 
       AddModelBindError(bindingContext, propertyDescriptor); 
      } 
      return; 
     } 
     if (propertyDescriptor.Name == "Priority") 
     { /* Other field binding ... */ 
      return; 
     } 
     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
    } 
} 

Come posso testare questo legante modello usando il test unitario VS? Abbiamo trascorso alcune ore su google, trovando esempi di coppie (http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx), ma questi esempi sono per MVC1 e non funzionano quando si utilizza MVC2.

Apprezzo il vostro aiuto.

risposta

41

ho modificato Hanselman's MVC 1 example per testare ASP.Net MVC leganti 2 modello ...

[Test] 
public void Date_Can_Be_Pulled_Via_Provided_Month_Day_Year() 
{ 
    // Arrange 
    var formCollection = new NameValueCollection { 
     { "foo.month", "2" }, 
     { "foo.day", "12" }, 
     { "foo.year", "1964" } 
    }; 

    var valueProvider = new NameValueCollectionValueProvider(formCollection, null); 
    var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(FwpUser)); 

    var bindingContext = new ModelBindingContext 
    { 
     ModelName = "foo", 
     ValueProvider = valueProvider, 
     ModelMetadata = modelMetadata 
    }; 

    DateAndTimeModelBinder b = new DateAndTimeModelBinder { Month = "month", Day = "day", Year = "year" }; 
    ControllerContext controllerContext = new ControllerContext(); 

    // Act 
    DateTime result = (DateTime)b.BindModel(controllerContext, bindingContext); 

    // Assert 
    Assert.AreEqual(DateTime.Parse("1964-02-12 12:00:00 am"), result); 
} 
+0

La tua risposta mi ha salvato dall'aggirarmi nella sorgente MVC. Ho provato a fare lo stesso aggiornamento e ho prodotto quasi lo stesso risultato. Sfortunatamente, non stavo impostando 'ModelMetaData' su' ModelBindingContext'. Senza di esso, si ottiene un 'NullReferenceException 'non ben definito in' BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext) '. – patridge

+0

Grazie per questo. Ha chiarito alcune cose per me bene. –

+0

Stavo per creare un ValueProvider personalizzato, ma grazie al NameValueCollectionValueProvider che hai menzionato. Questo è stato utile. Grazie. – Mani

1

L'approccio generale consiste nel creare un oggetto ControllerContext simulato, un modello ModelBindingContext mock e un oggetto PropertyDescriptor fittizio, quindi chiamare il metodo.

Se il tuo raccoglitore modello utilizza altri servizi, che assomiglia al tuo (si sta utilizzando NHibernate?), Quindi dovrai estrapolarli e fornire anche loro delle prese in giro.

codice di prova

L'unità sarà simile a questo:

// Arrange 
ControllerContext mockControllerContext = ...; 
ModelBindingContext mockModelBindingContext = ...; 
PropertyDescriptor mockPropertyDescriptor = ...; 
SomeService mockService = ...; 

TaskFormBinder taskFormBinder = new TaskFormBinder(); 
taskFormBinder.Service = mockService; 

// Act 
taskFormBinder.BindProperty(
    mockControllerContext, mockModelBindingContext, mockPropertyDescriptor); 

// Assert 
// ... here you need to inspect the values in the model binding context to see that it set the right properties 

Quale problema (s) stai avendo scrivere il test di unità?

+0

Solo bisogno di un esempio di beffardo ControllerContext, ModelBindingContext e PropertyDescriptor. Sì, sto usando NHibernate, ma so come astratto e mock questo livello. –

+0

Un problema con il mocking di 'ModelBindingContext' è che la sua proprietà più importante (' ModelType') non è virtuale, il che significa che i framework basati sull'ereditarietà (ad es. Moq) non possono prendere in giro il suo comportamento. –