2010-01-02 13 views
21

He escrito ligante modelo personalizado en el proyecto, que utiliza ASP.NET MVC 2. Este modelo se unen ligante sólo 2 campos de modelo:Unidad modelo personalizado de pruebas aglutinante en 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); 
    } 
} 

Cómo ¿Puedo probar este encuadernador modelo usando la prueba de unidad VS estándar? Pasé algunas horas buscando en Google, encuentro ejemplos de parejas (http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx), pero este ejemplo es para MVC1, y no funciona cuando se usa MVC2.

Agradezco su ayuda.

Respuesta

41

He modificado Hanselman's MVC 1 example para probar ASP.Net MVC 2 ligantes modelo ...

[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

Su respuesta me salvó de perder el tiempo en la fuente MVC. Intenté hacer la misma actualización y obtuve casi el mismo resultado. Desgraciadamente, no estaba configurando 'ModelMetaData' en' ModelBindingContext'. Sin él, obtienes una 'NullReferenceException' indescriptible en' BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext) '. – patridge

+0

Gracias por esto. Me despejó algunas cosas muy bien. –

+0

Estaba a punto de crear un ValueProvider personalizado, pero gracias al NameValueCollectionValueProvider que ha mencionado. Esto fue útil. Gracias. – Mani

1

El enfoque general es crear un ControllerContext falso, simular ModelBindingContext y Mock PropertyDescriptor, y luego llamar al método.

Si su carpeta de modelo utiliza otros servicios, que se parecen a los suyos (¿está utilizando NHibernate?), Tendrá que abstraerlos y proporcionar burlas de ellos también.

código de prueba

La unidad se verá algo como esto:

// 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 

¿Qué problema (s) estás teniendo escribir la prueba de la unidad?

+0

sólo necesitan un ejemplo de burla ControllerContext, ModelBindingContext y PropertyDescriptor. Sí, estoy usando NHibernate, pero sé cómo abstraer y simular esta capa. –

+0

Un problema con burlarse de 'ModelBindingContext' es que su propiedad más importante (' ModelType') no es virtual, lo que significa que los marcos basados ​​en herencia (por ejemplo, Moq) no pueden simular su comportamiento. –

Cuestiones relacionadas