2015-07-05 2 views
2

Я использую C# с nUnit для модульного тестирования моего проекта, и я пытаюсь написать некоторые модульные тесты, которые обеспечивают выполнение определенного исключения, но мои тесты продолжают терпеть неудачу. После большого количества тестов, чтобы решить эту проблему, мне удалось определить причину этого и создать небольшой пример кода, который показывает мои данные ниже.Почему мои тесты модуля C# для исключений не работают, если я использую try/catch?

Мой блок тестовый код:

[Test] 
    public void TestExceptionIsRaised() 
    { 
     var ex = Assert.Throws<UnauthorizedAccessException>(() => TestExceptionMethod()); 
     StringAssert.Contains("Attempted to perform an unauthorized operation", ex.Message); 
    } 

Мой метод без проверки ошибок:

public void TestExceptionMethod() 
{ 
    throw new UnauthorizedAccessException(); 
} 

Теперь, если я бегу, что модульное тестирование с описанным выше способом ... он бросает исключение, NUnit обнаруживает его и проходит тест. Тем не менее, этот код является проблемой, потому что он не имеет обработки ошибок и сбой, если я его выпустим так.

Итак, чтобы решить эту проблему, я добавляю некоторую обработку ошибок в мой метод, как это:

public void TestExceptionMethod() 
    { 
     try 
     { 
      throw new UnauthorizedAccessException(); 
     } 
     catch (UnauthorizedAccessException ex) 
     { 
      // Do something about the error 
     } 
    } 

Но теперь, когда я запускаю тест блока он терпит неудачу с этой ошибкой:

Expected: System.UnauthorizedAccessException But was: null

Так вместо того, чтобы выбирать между единичным тестом или правильной обработкой ошибок, я попытался повторить ошибку следующим образом:

public void TestExceptionMethod() 
     { 
      try 
      { 
       throw new UnauthorizedAccessException(); 
      } 
      catch (UnauthorizedAccessException ex) 
      { 
       // Do something about the error 
       throw; 
      } 
     } 

Наконец-то все работает. Единичный тест проходит каждый раз. И мой метод все еще может поймать ошибку и что-то сделать.

Однако из-за того, что я слышал, это не хорошая практика, чтобы повторять ошибки броска, подобные этому ??? Так что мне просто интересно, мое решение «правильно»? Или есть лучший способ модульного тестирования для исключения без необходимости удалять блоки try/catch из исходного метода?

ответ

2

However from what I've heard it isn't good practice to keep re-throwing errors like this???

Нет ничего плохого в повторных выбросах исключений. На самом деле лучше всего перебросить исключение после того, как ваше приложение запускает некоторый код регистрации без восстановления состояния вашего приложения.

Or is there a better way of unit testing for an exception without having to remove the try/catch blocks from the original method?

Я не уверен, что понимаю, что вы имеете в виду. Но если вы ожидаете, что исключение выбрано из вашего метода, должно быть исключение для вашего теста, независимо от того, выбрано ли оно напрямую или повторно выбрано. Если вы try/catch нравится:

public void TestExceptionMethod() 
    { 
     try 
     { 
      throw new UnauthorizedAccessException(); 
     } 
     catch (UnauthorizedAccessException ex) 
     { 
      // Do something about the error 
     } 
    } 

тест потерпит неудачу наверняка потому, что исключение поглотила. Тест не может обнаружить, что в методе есть исключение.

+0

О, я думаю, что я начинаю понимать, что вы имеете в виду. Единственное, что я до сих пор не понимаю, это то, что, прежде чем я начал писать модульные тесты для исключений, я никогда не использовал ключевое слово Throw. Я просто использовал Try {something} Catch (SomeException ex) {MessageBox.Show (ex.Message)}; и это отлично срабатывало, чтобы поймать исключения, даже если я не брошу их в блок catch. Поэтому я не уверен на 100%, почему это сработало, но теперь мне нужно повторно бросить их в блок catch для модульного теста для работы? – Calcolat

+1

@Calcolat: когда вы используете 'Assert.Throws', нужно исключить исключение' must'. Вы использовали 'Assert.Throws' в своем предыдущем модульном тесте? –

+0

Ах, я понял. Нет, я не использовал Assert.Throws раньше. Я только делал обычные модульные тесты, которые не проверяются на какие-либо исключения. Теперь я понимаю, что вы имеете в виду. Если я не тестирую исключения для исключения, мне не нужно повторно выбрасывать исключение. Но если я использую Assert.Throws, исключение должно быть выбрано, поэтому я должен повторно его выбросить. Верный? – Calcolat

1

Переводя тест на английский язык вы говорите:

"I expect the method TestExceptionMethod to throw a UnauthorizedAccessException. The message of which will contain a string with more details."

К не бросает исключение этот тест не будет никогда не пройти. Если вы не хотите, чтобы исключение было выбрано, вам нужно изменить свой тест. Если вы хотите, чтобы исключение было брошено, то вы делаете правильно.

Это правильно?

Это зависит. Если то, что вы делаете, является исключительной проблемой, а затем создайте исключение. Пусть программа выйдет из строя. Исправьте ошибку.

С другой стороны, если это то, чего можно ожидать, например, неправильный ввод данных, граничные условия, обрабатывайте его, если сможете. Если вы не можете оправиться от проблемы, выделите исключение.

0

Обработка исключений, сделанная плохо, может затруднить отладку, особенно при проглатывании исключения, или когда создается новый экземпляр исключения и теряется трассировка стека исходного исключения. Иногда последнее желательно, когда вам нужно более абстрактное исключение выше стека вызовов, и в этом случае вы можете добавить исходное исключение в качестве внутреннего исключения, чтобы сохранить доступ к трассировке стека.