Estoy publicando esta pregunta de nuevo a instancias del distinguido Sr. John Skeet, quien me sugirió que diseñe un programa de prueba simple que aísle y demuestre el problema que estoy enfrentando y vuelva a publicar la pregunta. Esta pregunta surgió de this one, así que, por favor, discúlpame si te suena muy familiar. Usted puede obtener detalles adicionales sobre esta pregunta a partir de ese.NUnit: ¿Por qué no Assert.Throws <T> Catch My ArgumentNullException?
El problema que estoy enfrentando se refiere a Assert.Throws<T>
de NUnit 2.5.9. Ocasionalmente, no detectará las excepciones lanzadas en el método invocado por TestDelegate. He delimitado este comportamiento de forma reproducible en el siguiente código. . (Aunque esto puede, ciertamente, ser un caso de falla en mi máquina ™
para reproducir el error, he creado una solución con proyectos # DLL dos C:
- La primera contiene una sola clase, con un único método público. Ese método es un método de extensión que encapsula la lógica necesaria para crear un
SqlCommand
, rellenar sus parámetros e invocarExecuteScalar
. Este proyecto no incluye otras referencias. - El segundo contiene una sola clase con dos métodos que prueba si el método en la primera DLL funciona o no como se esperaba. Este proyecto hace referencia a la primera, e incluye ar eferencia al Marco NUnit. No se hace referencia a otros ensambles.
Cuando camino a través de las pruebas en el depurador, observo lo siguiente:
Assert.Throws
invoca correctamente el métodoExecuteScalar<T>
extensión.- Los valores de los parámetros son nulos, como se esperaba.
ExecuteScalar<T>
prueba sus parámetros para valores nulos.- El depurador golpea y ejecuta la línea que contiene
throw new ArgumentNullException(...)
. - Después de ejecutar
throw
, el control de la aplicación no se transfiere inmediatamente alAssert.Throws
. En cambio, continúa en la siguiente línea enExecuteScalar<T>
. - Tan pronto como se ejecuta la siguiente línea de código, el depurador se rompe y muestra el error "Argument null exception no fue manejado por el código de usuario".
El código fuente que aísla este comportamiento se proporciona a continuación.
EL MÉTODO DE EXTENSIÓN
namespace NUnit_Anomaly
{
using System;
using System.Data;
using System.Data.SqlClient;
public static class Class1
{
public static T ExecuteScalar<T>(this SqlConnection connection, string sql)
{
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
using (var command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
return (T)command.ExecuteScalar();
}
}
}
}
los casos de prueba
namespace NUnit_Tests
{
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using NUnit.Framework;
using NUnit_Anomaly;
[TestFixture]
public class NUnitAnomalyTest
{
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
Assert.Throws<ArgumentNullException>(() => ((SqlConnection)null).ExecuteScalar<int>(null));
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
const string server = "MY-LOCAL-SQL-SERVER";
const string instance = "staging";
string connectionString = String.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;",
server,
instance);
using (var connection = new SqlConnection(connectionString))
{
Assert.Throws<ArgumentNullException>(() => connection.ExecuteScalar<int>(null));
}
}
}
}
El efecto neto es que las pruebas fallan cuando no deberían hacerlo. Según mi entender, Assert.Throws<T>
debería detectar mi excepción y la prueba debería pasar.
ACTUALIZACIÓN
Seguí el consejo de Hans y comprobó el diálogo Excepciones. No estaba rompiendo en lanzadas excepciones, pero estaba rompiendo en excepciones usuario no administrado. Aparentemente, es por eso que el depurador irrumpe en el IDE cuando se lanza la excepción. Al borrar la casilla de verificación se solucionó el problema y Assert.Throws<T>
lo recogió. Sin embargo, si no he hecho esto, no puedo presionar F5 para continuar la ejecución, o la excepción se convertirá en NullReferenceException
.
Así que ahora la pregunta es: ¿Puedo configurar saltos de excepción por proyecto? Solo quiero hacer esto cuando estoy probando, pero no en general.
Debug + Exceptions, asegúrese de que las casillas de verificación de Thrown estén desactivadas. –
@ Hans Passant: he verificado que ninguna de las casillas lanzadas está marcada. –