Pregunta

Antes de empezar, quiero dejar claro que yo ya he comprobado de soluciones en tanto esta pregunta y esta pregunta .

El Método de Prueba

public static DataSet ExecuteDataSet(this SqlConnection connection, string sql)
{
    if (null == connection || null == sql)
    {
        throw new ArgumentNullException();
    }

    using (var command = connection.CreateCommand())
    {
        // Code elided for brevity
    }
}

Los métodos de ensayo

[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteDataSetThrowsForNullConnection()
{
    ((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}

[Test]
public void ExecuteDataSetThrowsForNullSql()
{
    Assert.Throws<ArgumentNullException>(
        () => Resource.Connection.ExecuteDataSet(null)
    );
}

El comportamiento impar

Ninguna de las versiones de la prueba método es la captura de la ArgumentNullException que se produce inmediatamente después de entrar el método ExecuteDataSet. El control de flujo continúa con la siguiente línea (using (var command = connection.CreateCommand())) y una NullReferenceException está ocurriendo en su lugar (que, por supuesto, no es manejado por cualquiera de mis casos de prueba, porque que nunca debería ser lanzado ).

Originalmente, el primer método de prueba (ExecuteDataSetThrowsForNullConnection) se parecía a la segunda (ExecuteDataSetThrowsForNullSql). Cuando Assert.Throws no pudo detectar la excepción, hice algunas investigaciones y señaló que algunas personas recomendó el uso de ExpectedException lugar. He modificado el código de prueba en consecuencia, pero en vano.

Para el registro, esto es 32-bit de código .NET 3,5, probado bajo NUnit 2.5.9. Estoy usando TestDriven.NET para la integración de Visual Studio, y tener las últimas versiones de NCover y NDepend instalado.

TL; DR pregunta

¿Por qué no son los métodos de ensayo para controlar el excepción que se produce, y cómo lo arreglo?

editar

Esta versión del método de prueba funciona.

[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
    try
    {
        ((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
    }
    catch(ArgumentNullException e)
    {
        Assert.AreEqual(true, true);
    }
    catch (Exception e)
    {
        Assert.Fail("Expected ArgumentNullException, but {1} was thrown instead.", e.GetType().Name);
    }
}
¿Fue útil?

Solución

Mi conjetura es que usted no está realmente probar el código que cree que está. Trate de poner algunas declaraciones Console.WriteLine y ver si están impresos. Si se pone un punto de interrupción en la declaración throw y ejecutar las pruebas en el depurador, lo hace el punto de interrupción recibe un golpe? Si el control se pasa a la siguiente instrucción, eso significa que la excepción es que nunca son lanzadas - que no puede ser capturado de una manera que permitiría la ejecución continúe en el método de lanzamiento, a menos que haya encontrado un realmente raro insecto CLR.

He escrito lotes de código como este y nunca ha fallado en NUnit.

Como acotación al margen, lo ven como una buena práctica incluir el nombre del parámetro en ArgumentExceptions, así que me he escrito:

if (connection == null)
{
    throw new ArgumentNullException("connection");
}
if (sql == null)
{
    throw new ArgumentNullException("sql");
}

Esto tiene el desafortunado problema de ser prolijo y repitiendo los nombres de los parámetros en el código como cadenas ... pero es razonablemente fácil de hacerlo bien (especialmente con ReSharper ayudar a validar los nombres) y que podría ser muy útil si esto alguna vez desencadenantes de la producción. (Hay algunos cortes de mala muerte para validar los argumentos de otras maneras, pero sospecho que no quiere ver a los ...)

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