Domanda

Prima di cominciare, voglio chiarire che ho già controllato per le soluzioni sia questa domanda e questa domanda .

Il Metodo di prova

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
    }
}

I metodi di prova

[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)
    );
}

Il comportamento dispari

Né versione del test metodo sta recuperando la ArgumentNullException che viene gettato immediatamente entrando il metodo ExecuteDataSet. Controllare il flusso procede alla riga successiva (using (var command = connection.CreateCommand())) ed un NullReferenceException si sta verificando, invece (che, ovviamente, non è gestita da uno dei miei casi di test, perché Non dovrebbe mai essere gettati ).

In origine, il primo metodo di prova (ExecuteDataSetThrowsForNullConnection) sembrava proprio come il secondo (ExecuteDataSetThrowsForNullSql). Quando Assert.Throws non è riuscito a intercettare l'eccezione, ho fatto qualche ricerca e ho notato che alcune persone consiglia di utilizzare ExpectedException invece. Ho modificato il codice di prova di conseguenza, ma senza alcun risultato.

Per la cronaca, questo è a 32 bit di codice .NET 3.5, testato in NUnit 2.5.9. Sto usando TestDriven.NET per Visual Studio integrazione, e hanno le ultime versioni di NCover e NDepend installato.

TL; DR domanda

Perché non sono i metodi di prova cattura l'eccezione che viene generata, e come posso risolvere il problema?

Modifica

Questa versione del metodo di prova funziona.

[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);
    }
}
È stato utile?

Soluzione

La mia ipotesi è che non sei veramente testando il codice che pensi di essere. Prova a mettere alcune dichiarazioni Console.WriteLine e vedere se sono stampate. Se si mette un punto di interruzione sulla dichiarazione throw ed eseguire le prove nel debugger, fa il punto di interruzione essere colpito? Se il controllo passa all'istruzione successiva, significa che l'eccezione non è mai gettati - non può assolutamente essere catturato in un modo che avrebbe permesso l'esecuzione continuare nel metodo di lancio, a meno che non avete trovato un davvero strano CLR bug.

ho scritto un sacco di codice come questo e non è mai riuscito a NUnit.

Per inciso, mi vedono come buona pratica includere il nome del parametro in ArgumentExceptions, così avrei scritto:

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

Questa è la sfortunata problema di essere prolisso e ripetendo i nomi dei parametri nel codice come stringhe ... ma è ragionevolmente facile da ottenere (in particolare con ReSharper aiuta a convalidare i nomi) e potrebbe essere davvero utile se questo mai trigger in produzione. (Ci sono alcuni hack grotty per convalidare gli argomenti in altri modi, ma ho il sospetto che non si vuole vedere quelli ...)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top