Я отправляю этот вопрос заново по воле уважаемого г-на Джона Скита, который предложил мне разработать простую тестовую программу, которая изолирует и демонстрирует проблему, с которой я сталкиваюсь и пересказываю вопрос. Этот вопрос вырос из этого, поэтому, пожалуйста, простите меня, если все это звучит очень знакомо. Вы можете потенциально собрать дополнительные сведения об этом вопросе из этого.
Проблема, с которой я встречаю Assert.Throws<T>
от NUnit 2.5.9. Иногда он не сможет поймать какие-либо исключения, вызванные методом, вызванным TestDelegate. Я приписал это поведение воспроизводимым образом в приведенном ниже коде. (Хотя это может быть, по общему признанию, случай Fails On My Machine ™.
Чтобы воспроизвести ошибку, я создал решение с двумя DLL-проектами С#:
- Первый содержит один класс с одним общедоступным методом. Этот метод является методом расширения, который инкапсулирует логику, необходимую для создания
SqlCommand
, заполняет ее параметры и вызываетExecuteScalar
на нем. Этот проект не содержит других ссылок. - Второй содержит один класс с двумя методами, которые проверяют, работает ли метод в первой DLL как ожидалось. Этот проект ссылается на первый и включает ссылку на NUnit Framework. Никакие другие сборки не указаны.
Когда я выполняю тесты в отладчике, я наблюдаю следующее:
-
Assert.Throws
корректно вызывает метод расширенияExecuteScalar<T>
. - Значения параметров равны нулю, как и ожидалось.
-
ExecuteScalar<T>
проверяет параметры для нулевых значений. - Отладчик делает и выполняет строку, содержащую
throw new ArgumentNullException(...)
. - После выполнения
throw
управление приложением сразу не переносится наAssert.Throws
. Вместо этого он продолжается на следующей строке вExecuteScalar<T>
. - Как только выполняется следующая строка кода, отладчик прерывается и отображает ошибку "Исключение для аргумента null исключение было необработанным кодом пользователя".
Исходный код, который изолирует это поведение, приведен ниже.
МЕТОД РАСШИРЕНИЯ
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();
}
}
}
}
ИСПЫТАТЕЛЬНЫЕ СЛУЧАИ
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));
}
}
}
}
Чистый эффект заключается в том, что тесты терпят неудачу, когда они не должны. Насколько мне известно, Assert.Throws<T>
должен поймать мое исключение, и тест должен пройти.
UPDATE
Я взял совет Ганса и проверил диалог Исключения. Я не нарушал брошенных исключений, но я нарушал необработанные пользовательские исключения. По-видимому, именно поэтому отладчик ломается в среде IDE при вызове исключения. Устранение флажка устранило проблему, а Assert.Throws<T>
взял ее. Однако, если я этого не сделал, я не могу просто нажать F5 для продолжения выполнения, иначе исключение станет NullReferenceException
.
Итак, теперь возникает вопрос: могу ли я настраивать разрывы исключений для каждого проекта? Я только хочу это сделать, когда тестирую, но не в общем.