c# - example - ¿Cómo manejar las excepciones generadas por las tareas en el comando Assert.thhrows de xUnit.net?
assert c# ejemplos (2)
La siguiente prueba asíncrona de xUnit.net
con un lambda
marcado con el modificador async
falla al informar que no se lanzó ninguna excepción:
[Theory, AutoWebData]
public async Task SearchWithNullQueryThrows(
SearchService sut,
CancellationToken dummyToken)
{
// Fixture setup
// Exercise system and verify outcome
Assert.Throws<ArgumentNullException>(async () =>
await sut.SearchAsync(null, dummyToken));
// Teardown
}
Para asegurarme de que se ArgumentNullException
realmente una ArgumentNullException
utilicé explícitamente un bloque try-catch
. Funcionó, sin embargo, el código resultante no está limpio (en comparación con la primera prueba):
[Theory, AutoWebData]
public async Task SearchWithNullQueryThrows(
SearchService sut,
CancellationToken dummyToken)
{
// Fixture setup
var expected = typeof(ArgumentNullException);
Type actual = null;
// Exercise system
try
{
await sut.SearchAsync(null, dummyToken);
}
catch (ArgumentNullException e)
{
actual = e.GetType();
}
// Verify outcome
Assert.Equal(expected, actual);
// Teardown
}
¿Por qué Assert.Throws<T>
con la lambda
marcada con el modificador async
?
Si también necesita devolver la excepción para verificarla, esto podría ser útil:
public static async Task<Exception> AssertThrowsAsync<TException>(Func<Task> func)
{
var expected = typeof (TException);
Exception exception = null;
Type actual = null;
try
{
await func();
}
catch (Exception e)
{
actual = e.GetType();
exception = e;
}
Assert.NotNull(exception);
Assert.Equal(expected, actual);
return exception;
}
Actualizar
Esto se ha resuelto en xUnit 2, con la adición de Assert.ThrowsAsync
.
Estoy sospechando que Assert.Throws
no es async
. Recomiendo plantear este problema con el equipo de xUnit, sugiriendo que se ThrowsAsync
un ThrowsAsync
.
Un delegado async
en este caso está devolviendo Task
o Task<T>
, y la ArgumentNullException
no se elimina directamente del delegado; en su lugar, se coloca en la Task
( Task.Exception.InnerException
). Assert.Throws
espera que la excepción se Assert.Throws
directamente del delegado, no se coloque en una propiedad del valor de retorno.
Puede crear su propio AssertEx.ThrowsAsync
como tal:
public static async Task ThrowsAsync<TException>(Func<Task> func)
{
var expected = typeof(TException);
Type actual = null;
try
{
await func();
}
catch (Exception e)
{
actual = e.GetType();
}
Assert.Equal(expected, actual);
}
Que se puede utilizar como tal:
[Theory, AutoWebData]
public async Task SearchWithNullQueryThrows(
SearchService sut,
CancellationToken dummyToken)
{
// Fixture setup
// Exercise system and verify outcome
await AssertEx.ThrowsAsync<ArgumentNullException>(async () =>
await sut.SearchAsync(null, dummyToken));
// Teardown
}
Yo uso un enfoque similar en MSTest.