Autofixture: Trate a los delegados como falsos con FakeItEasy

Creado en 16 feb. 2018  ·  15Comentarios  ·  Fuente: AutoFixture/AutoFixture

Hasta donde yo sé, AutoFixture trata automáticamente las interfaces y los tipos abstractos como simulacros. Creo que es una buena idea incluir también los tipos de delegado en esta lista.

enhancement good first issue

Comentario más útil

¡Lanzado en v4.2.0! Para permitir:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

Todos 15 comentarios

En primer lugar, ¿podría aclarar con qué marco de simulación trabaja? Tenemos algunas integraciones (Moq, NSubsitute, FakeItEasy), por lo que no está claro. Hasta donde yo sé, los delegados ya son compatibles con la integración de Moq (al menos eso se menciona en el n. ° 742).

Además, hasta donde yo sé, AutoFixture tiene su propio mecanismo de generación de delegados. ¿Tiene algún problema con él?

@zvirja Yo uso FakeItEasy. Así que cambiaré el título del problema.
El siguiente código devuelve una falsificación después de la personalización aplicada:
var myFake= fixture.Create<ISomeInterface>();

Sin embargo, lo siguiente no lo hace:
var myFake= fixture.Create<Func<int,int>>();

El código anterior solo devuelve un delegado ficticio no falso.

Además, las siguientes fallas con un error:

var myFake= fixture.Create<Fake<Func<int,int>>>();

AutoFixture.ObjectCreationExceptionWithPath
HResult = 0x80131500
Mensaje = AutoFixture no pudo crear una instancia desde System.IntPtr porque la creación falló inesperadamente con una excepción. Consulte la excepción interna para investigar la causa raíz del error.

Ruta de solicitud:
FakeItEasy.Fake 1[System.Func 2 [System.Int32, System.Int32]]
Método IntPtr
System.IntPtr

Mensajes de excepción internos:
AutoFixture.Kernel.IllegalRequestException: se detectó una solicitud para un IntPtr. Este es un recurso inseguro que bloqueará el proceso si se usa, por lo que se rechaza la solicitud. Una fuente común de solicitudes IntPtr son las solicitudes de delegados como Funco acción. Si este es el caso, la solución alternativa esperada es personalizar (registrar o inyectar) el tipo infractor especificando una estrategia de creación adecuada.

Fuente =
StackTrace:

Excepción interna 1:
IllegalRequestException: se detectó una solicitud para un IntPtr. Este es un recurso inseguro que bloqueará el proceso si se usa, por lo que se rechaza la solicitud. Una fuente común de solicitudes IntPtr son las solicitudes de delegados como Funco acción. Si este es el caso, la solución alternativa esperada es personalizar (registrar o inyectar) el tipo infractor especificando una estrategia de creación adecuada.

@OnurGumus He investigado brevemente este problema y no parece que FakeItEasy admita la burla de los delegados. Los delegados no se mencionan en su documentación.

También probé el siguiente código y falló con una excepción (lo que demuestra que la función no es compatible):
c# A.Fake<Func<int, int>>();

Por lo tanto, no parece que AutoFixture pueda hacer algo al respecto también.

¿Podría describir el comportamiento deseado con más detalle? Es muy fácil simular un delegado, ya que podría especificarse a través de una expresión lambda primitiva, entonces, ¿por qué necesita simulacros?

@zvirja , FakeItEasy ciertamente es compatible con las falsificaciones para los delegados:
image

@blairconrad ¿Podrías

Gracias: guiño:

@zvirja , feliz de hacerlo. Como dice @OnurGumus , FakeItEasy felizmente falsificará a los delegados (y he creado un problema para documentar esto).
Sin embargo, AutoFakeItEasy nunca se ha molestado en falsificar delegados.

Al fingir un Fake<Func<int, int>> , por ejemplo, FakeItEasyMethodQuery.SelectMethods falla porque no considera el caso Fake<T> donde T es un delegado. El cambio muy ingenuo a continuación rectifica esto.

@@ -33,7 +33,7 @@ namespace Ploeh.AutoFixture.AutoFakeItEasy
             }

             var fakeType = type.GetFakedType();
-            if (fakeType.IsInterface)
+            if (fakeType.IsInterface || fakeType.IsSubclassOf(typeof(Delegate)))
             {
                 return new[] { new ConstructorMethod(type.GetDefaultConstructor()) };
             }

Entonces puedo crear y usar un Fake<Func<int, int>> .

En cuanto a la creación de un Func<int, int> , lo probé rápidamente y descubrí que el dispositivo usaba DelegateGenerator para crear un delegado (no FakeItEasy).
Entre tú y yo, siempre me ha confundido la arquitectura AutoFixture y la relación entre un constructor y un relé y todo eso, pero puedo seguir explorando y ver dónde está la brecha.

Volví. Puedo entender. El FakeItEasyRelay se agrega a los recolectores de residuos del dispositivo, pero el DelegateGenerator crea un delegado primero.
Una búsqueda rápida no reveló cómo insertar el constructor FakeItEasy al principio de la cadena, pero es posible que no me vea bien.

Independientemente de cómo resulte esto, me complacerá enviar un PR para permitir la burla de Fake<TDelegate> donde TDelegate es un tipo de delegado.

@blairconrad como usuario de FakeItEasy Anhelo tu PR :)

@blairconrad ¡ Gracias por las aclaraciones y por su investigación! Acabo de comprobarlo una vez más y descubrí que FakeItEasy de hecho crea las falsificaciones para los delegados. Probablemente, me perdí algo en mi prueba anterior 😖

En cuanto a la creación de un Func, Lo intenté rápidamente y descubrí que el dispositivo usaba DelegateGenerator para crear un delegado (no FakeItEasy).

Sí. Tenemos exactamente el mismo problema con Moq: AutoFixture intercepta esas solicitudes antes de que ResidueCollectors tengan la oportunidad de intervenir.

Sugeriría solucionar este problema de la siguiente manera:

  • Extender la consulta del método para admitir solicitudes Fake<Delegate> ;
  • Agregue una nueva personalización, que agregará relevo a la colección Customizations , de modo que la solicitud de delegado sea manejada (retransmitida) _antes_ de ser procesada por el kernel de AutoFixture. Es decir, esa función no se activará de forma predeterminada, sin embargo, los usuarios podrían habilitarla fácilmente mediante una personalización predefinida.

@blairconrad Además, ¿podría describir cuál es el beneficio del delegado falso sobre el creado por AutoFixture? Por ahora, solo me viene a la mente una cosa: puede configurarlos usando la sintaxis de configuración de biblioteca falsa.

Gracias, @zvirja.

Creo que tienes razón. El beneficio de un delegado falso sería que podría configurarse utilizando la sintaxis de configuración de biblioteca falsa.

Me complace extender la consulta del método para admitir Fake<Delegate> , y agregaré una personalización adicional tal como dice, pero me pregunto: ¿es lo suficientemente bueno uno que admita Delegate ? ¿Qué sucede cuando los siguientes deseos de error reportados IEnumerable o Task o IDictionary fueron falsificados por FakeItEasy?

Oh, @zvirja ha pedido confirmación sobre la sintaxis para simular un delegado. Ahora se ha fusionado en la documentación de FakeItEasy con FakeItEasy / FakeItEasy # 1321, pero para ser explícito:

`` c #
var fakeDelegate = A.Fake> ();

is the preferred syntax for clients, although "unnatural fakes" can be used:

```c#
var fakeDelegate = new Fake<Func<int, int>>();

Esto último es cómo la clase FakeItEasyBuilder crearía el Fake.

Dato curioso: la falsificación de delegados no se admitió hasta la versión 1.7.4257.42 (probablemente cometa FakeItEasy / FakeItEasy @ edb4f61d0db0a84b68c7a9395f2661a58579d34a). Personalmente, no tengo ningún problema en decir "no obtienes esto a menos que uses al menos esa versión de FakeItEasy". @zvirja u otros, ¿consideras esto un problema? Tendré que hacer algunos trucos con las pruebas unitarias para asegurarme de no romper las pruebas AutoFakeItEasyUnitTest existentes.
A menos que desee actualizar la versión mínima de FakeItEasy para esta corrección. Probablemente no lo haría, especialmente porque solicitar un delegado habría fallado en esas versiones de todos modos.

@blairconrad ¡ Muchas gracias por tu trabajo en eso!

@zvirja u otros, ¿consideras esto un problema?

No en absoluto. De acuerdo con SemVer que estamos siguiendo aquí, no podemos cambiar la versión de dependencia dentro de la misma versión principal. Por lo tanto, diría que el paso correcto sería agregar dicho soporte para las versiones de FakeItEasy que admiten la función. Más adelante, es posible que deseemos eliminar el soporte 1.x en v5 (por coherencia), pero eso sucederá solo en el futuro.

Convirtiendo este problema en una función, como acordamos proceder con él (y FakeItEasy admite delegados).

¡Lanzado en v4.2.0! Para permitir:
c# fixture.Customize(new AutoFakeItEasyCustomization { GenerateDelegates = true });

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

ploeh picture ploeh  ·  7Comentarios

Accc99 picture Accc99  ·  4Comentarios

zvirja picture zvirja  ·  4Comentarios

TroyHouston picture TroyHouston  ·  6Comentarios

josh-degraw picture josh-degraw  ·  4Comentarios