Является ли NUnit ExpectedExceptionAttribute единственным способом проверки, если что-то вызывает исключение? - PullRequest
5 голосов
/ 03 ноября 2008

Я совершенно новый в C # и NUnit.

В Boost.Test есть семейство макросов BOOST_*_THROW. В тестовом модуле Python есть метод TestCase.assertRaises.

Насколько я понимаю, в C # с NUnit (2.4.8) единственным методом выполнения теста исключений является использование ExpectedExceptionAttribute.

Почему я должен предпочесть ExpectedExceptionAttribute, скажем, подходу Boost.Test? Какие рассуждения могут стоять за этим дизайнерским решением? Почему это лучше в случае C # и NUnit?

Наконец, если я решу использовать ExpectedExceptionAttribute, как я могу выполнить некоторые дополнительные тесты после того, как исключение было поднято и перехвачено? Допустим, я хочу проверить требование о том, что объект должен быть действительным после того, как какой-то установщик поднял System.IndexOutOfRangeException. Как бы вы исправили следующий код для компиляции и работы, как ожидалось?

[Test]
public void TestSetterException()
{
    Sth.SomeClass obj = new SomeClass();

    // Following statement won't compile.
    Assert.Raises( "System.IndexOutOfRangeException",
                   obj.SetValueAt( -1, "foo" ) );

    Assert.IsTrue( obj.IsValid() );
}

Редактировать: Спасибо за ваши ответы. Сегодня я нашел Это запись в блоге Тесты , где упоминаются все три описанных вами метода (и еще один незначительный вариант). Жаль, что я не смог найти его раньше: - (.

Ответы [ 5 ]

13 голосов
/ 03 ноября 2008

Я удивлен, что еще не видел упомянутый образец. Дэвид Арно очень похож, но я предпочитаю простоту этого:

try
{
    obj.SetValueAt(-1, "foo");
    Assert.Fail("Expected exception");
}
catch (IndexOutOfRangeException)
{
    // Expected
}
Assert.IsTrue(obj.IsValid());
10 голосов
/ 03 ноября 2008

Если вы можете использовать NUnit 2.5, там есть несколько помощников .

Assert.That( delegate { ... }, Throws.Exception<ArgumentException>())
4 голосов
/ 03 ноября 2008

Синтаксис MbUnit:

Assert.Throws<IndexOutOfRangeException>(delegate {
    int[] nums = new int[] { 0, 1, 2 };
    nums[3] = 3;
});
2 голосов
/ 03 ноября 2008

Ваш предпочтительный синтаксис:

Assert.Raises( "System.IndexOutOfRangeException",
               obj.SetValueAt( -1, "foo" ) );

В любом случае, я не могу работать с C # - obj.SetValueAt будет оценен, а результат передан Assert.Raises Если SetValue выдает исключение, вы никогда не попадете в Assert.Raises.

Вы можете написать вспомогательный метод, чтобы сделать это:

void Raises<T>(Action action) where T:Exception {
   try {
      action();
      throw new ExpectedException(typeof(T));
   catch (Exception ex) {
      if (ex.GetType() != typeof(T)) {
         throw;
      }
   }
}

, который допускает подобный синтаксис:

Assert.Raises<System.IndexOutOfRangeException>(() => 
  obj.SetValueAt(-1, "foo")
;
2 голосов
/ 03 ноября 2008

Я всегда придерживался следующего подхода:

bool success = true;
try {
    obj.SetValueAt(-1, "foo");
} catch () {
    success = false;
}

assert.IsFalse(success);

...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...