método Fixture.CreateAnonymous mata proceso corredor de prueba con un error (AutoFixture) cuando se utiliza AutoMoq para crear un controlador

StackOverflow https://stackoverflow.com/questions/3514102

Pregunta

Estoy tratando de utilizar el AutoMoqCustomization con AutoFixture para crear un controlador de MVC2 ASP.NET en una prueba de unidad a través del método Fixture.CreateAnonymous. He intentado tanto en xUnit bajo TestDriven.NET, la interfaz gráfica de usuario de prueba xUnit y en MSTest y todos tienen el mismo resultado: un gran fracaso del proceso de ejecución de la prueba. En Windows 7 x64 si lo que importa.

Para reproducir, basta con crear un nuevo proyecto ASP.NET MVC2, añadir las referencias a AutoFixture, AutoMoq y Moq (3.1, según la fuente AutoMoq) y tratar el siguiente (repro VS2010 enlace MVC2 proyecto más adelante):

[TestMethod]
public void Index()
{
 var fixture = new Fixture().Customize(new AutoMoqCustomization());
    // here's where the error in the test host occurs:
 HomeController controller = fixture.CreateAnonymous<HomeController>();
}

En MSTest el error lee:

  

El tiempo de ejecución ha detectado un error grave. La dirección del error estaba en 0x6465f370, en la rosca 0x2684. El código de error es 0xc0000005. Este error puede ser un error en el CLR o en las porciones no seguros o no verificables de código de usuario. Las fuentes comunes de este error incluyen errores de cálculo de referencias del usuario para interoperabilidad COM-o PInvoke, lo que podría producir daños en la pila.

AfWithMvc repro proyecto (de SkyDrive)

¿Fue útil?

Solución

solución sugerida

Para comenzar con una posible solución, esto debe parar el romper:

var fixture = new Fixture().Customize(new AutoMoqCustomization());
// This should fix the problem for all Controllers
fixture.Customize<ViewDataDictionary>(c =>
    c.Without(x => x.ModelMetadata));

HomeController controller = fixture.CreateAnonymous<HomeController>();

Explicación

Y ahora para la explicación:

Este error es causado por la prueba de AutoFixture autoproperties función de tratar de asignar un valor a HomeController.ViewData.ModelMetaData. La clase ModelMetaData tiene este constructor:

public ModelMetadata(
    ModelMetadataProvider provider,
    Type containerType,
    Func<object> modelAccessor,
    Type modelType,
    string propertyName)

El culpable aquí es el parámetro modelAccessor. Para llenar ese AutoFixture propiedad (en lugar sin pensar) refleja el tipo y descubre este único constructor:

public Func(object @object, IntPtr method)

excavación adicional, la primera AutoFixture constructor IntPtr puede satisfacer es ésta:

public unsafe IntPtr(int value)

Por defecto, Int32 casos se crean por una secuencia creciente determinista , por lo value en este caso probablemente será 1 o 2 o un entero pequeño similar. En otras palabras, ahora tenemos un muy válido puntero inseguros en nuestras manos, y esto está haciendo el bloqueo de proceso.

Ahora, en circunstancias normales debería ser capaz de solucionar este problema mediante el registro de un Func<object> con el aparato y todo debe ser Dandy:

fixture.Register<Func<object>>(() => () => new object());

Sin embargo, he intentado esto con su repro y aunque el proceso ya no se bloquea en la misma forma, las pruebas de funcionamiento durante mucho tiempo y finalmente se estrella con un OutOfMemoryException.

No sé lo que ASP.NET MVC hace con Func<object>, pero parece ser que lo usa bastante heaviliy.

Los restos cuestión de si se trata de un error en AutoFixture?

Creo que no lo es. Si bien es definitivamente menos que ideal, AutoFixture no Funcs tratar o acciones de manera diferente de otros tipos, por lo que vemos este comportamiento.

Este comportamiento particular podría posiblemente ser abordado mediante la adición de un apoyo específico para Func<TResult>, sino para permanecer rígido sino que también debe tener soporte para Func<T, TResult>, Func<T1, T2, TResult>, etc. AFAIR en .NET 4 hay mucho de estos tipos de delegado (también de acción, etc.), por lo que significaría añadir soporte para una gran cantidad de tipos.

Pero, ¿qué pasa con todos los otros tipos que tienen un IntPtr en su constructor? AutoFixture no puede saber acerca de todos ellos, así que esto no parece ser una dirección viable.

Sin embargo, lo que podría tiene es un guardia que le impide intentar para crear instancias IntPtr en primer lugar . Esta muy probable que se añade antes de la 2,0 RTW.

Gracias por informar de este.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top