Como se discutió en # 268, la clase GuardClauseAssertion
no espera a que se completen las tareas, por lo que no puede validar métodos rápidos que no
Esto es completamente comprensible, ya que el fail fast es de hecho la mejor opción. Sin embargo, parece imposible implementar un comportamiento async
.
parece imposible implementar el comportamiento _fail fast_ cuando se trata de métodos marcados con la palabra clave
async
.
¿Cómo es eso? ¿Puede dar un ejemplo?
@ploeh Básicamente, el método _cualquier_ async
no es rápido. Considere el siguiente ejemplo:
`` c #
Tarea asíncrona pública
{
if (arg == null) lanza una nueva ArgumentNullException (nameof (arg));
await Task.Yield();
return default;
}
''
Este método no lanza si lo llamas null
. En su lugar, se devuelve el Task
fallido. Por lo tanto, GuardClauseAssertion en su forma actual falla y se queja de la falta de una cláusula de guardia.
En una aplicación real, casi todo el código es async
, por lo tanto, cada invocación es awaited
y la excepción se lanza inmediatamente. Por lo tanto, está completamente bien que se viole el principio de "falla rápida" en una forma en la que debe await
Task para ver la excepción.
Por supuesto, puede volver a escribir el código de alguna manera para que falle inmediatamente (cree una función privada con la palabra clave async
y mueva toda la lógica allí), pero no tiene sentido hacerlo.
En la aplicación real, casi todo el código es
async
, por lo tanto, cada invocación esawaited
y la excepción se lanza inmediatamente.
Ese es un buen punto; Acepto ese argumento.
A veces me desvío cuando alguien afirma o insinúa (con poca evidencia) que algo es _imposible _ ...
A veces me desvío cuando alguien afirma o insinúa (con poca evidencia) que algo es imposible ...
Sí, es bastante justo 😉
Ahora déjeme intentar pensar cómo puedo rediseñar GuardClauseAssertion
para que no tenga una bandera booleana; para ser justos, tampoco me gusta. Nos vemos más tarde en PR.
Ahora déjame intentar pensar cómo puedo rediseñar
GuardClauseAssertion
para que no tenga una bandera booleana
Creo que, como sugirió @moodmosaic , una nueva clase podría ser un mejor diseño. Sin embargo, no he investigado mucho el problema, así que me reservo el derecho a equivocarme 😄
Aquí está la solución que he estado usando.
async
de la firma del métodoasync
Ejemplo:
public Task<int> GetNumberAsync(MyObject obj)
{
// Fail-fast behavior
if (request is null)
throw new ArgumentNullException(nameof(obj));
async Task<int> work()
{
var items = await obj.GetItemsAsync(); // whatever you need to call
return items.Count();
}
return work();
}
Ha sido una buena solución para mi. Gracias por tu ayuda.
@mniak Es interesante tener un ejemplo concreto de lo que @zvirja sugirió aquí .
Personalmente, no me gusta mucho porque estamos contaminando el método con "trucos" en beneficio del marco de prueba, que me huele muy mal y no quisiera que mi equipo usara este patrón.
Manténgalo abierto para implementar el soporte de forma nativa. Un día. En un futuro cercano. O solo un día.
Hola. Nos topamos con exactamente este problema y nos sorprendió que no exista una buena solución hasta ahora.
¿Hay razones para no implementar una nueva clase para esto?
No conozco los detalles internos de AutoFixture, pero si tuviéramos un MethodInfo disponible dentro de la clase GuardClauseAssertion para el método de prueba, podemos echar un vistazo a sus CustomAttributes e identificar si es un método Async o no (https: / /stackoverflow.com/a/20350646). Entonces, tal vez, un interruptor (bool versus nueva clase) ni siquiera sea necesario.
@zvirja @aivascu ¿ podríamos reconsiderar esto? Realmente no veo por qué en 2021 los métodos asíncronos no se pueden probar correctamente.
@Kralizek si leo la situación correctamente, la solicitud no ha sido rechazada, e incluso hay un PR que la arregla.
Eché un vistazo breve a las relaciones públicas y debo decir que estoy de acuerdo con los comentarios que recibió.
Entonces, lo único que queda es implementar la retroalimentación o presentar un nuevo RP con la retroalimentación implementada.
No pude ver el PR vinculado en la aplicación móvil 😅
Comentario más útil
@ploeh Básicamente, el método _cualquier_
async
no es rápido. Considere el siguiente ejemplo:`` c #GuardedOpenGenericMethodReturningTaskResult(objeto arg)
Tarea asíncrona pública
{
if (arg == null) lanza una nueva ArgumentNullException (nameof (arg));
}
''
Este método no lanza si lo llamas
null
. En su lugar, se devuelve elTask
fallido. Por lo tanto, GuardClauseAssertion en su forma actual falla y se queja de la falta de una cláusula de guardia.En una aplicación real, casi todo el código es
async
, por lo tanto, cada invocación esawaited
y la excepción se lanza inmediatamente. Por lo tanto, está completamente bien que se viole el principio de "falla rápida" en una forma en la que debeawait
Task para ver la excepción.Por supuesto, puede volver a escribir el código de alguna manera para que falle inmediatamente (cree una función privada con la palabra clave
async
y mueva toda la lógica allí), pero no tiene sentido hacerlo.