2015-01-26 5 views
6

Я пишу некоторые модульные тесты, используя интегрированную инфраструктуру Visual Studio. Мне нужно написать несколько тестовых примеров, которые передаются при создании правильного исключения. Проблема в том, что исключения, которые мне нужно проверить, - это внутренние исключения, вложенные в более общий. Есть ли какое-то простое решение или мне нужно расширить всю функциональность. В настоящее время я использую атрибут [ExpectedException], но в такой ситуации он не будет очень хорош.Тестирование модулей для внутренних исключений

Мне также интересно, что происходит, когда мы используем [ExpectedException], в то время как у нас также есть логика Assert в самом тесте. Являются ли оба условия оценены (исключение выбрано и утверждение Assert оказалось действительным), или тест проходит сразу после того, как выбрано правильное исключение?

+0

Не используйте атрибут «ExpectedException» (тест может пройти из-за какой-либо фазы аранжировки, вызванного тем же самым исключением, а не фазой действия); Используйте 'Assert.Throws ' –

+0

В структуре VS нет метода «Броски». Для большинства случаев я использую пользовательские исключения, чтобы сделать использование атрибута достаточно точным. – zhulien

ответ

7

Если структура не поддерживает пользовательские метания, обычно есть два варианта:

  1. Реализовать это себе
  2. Change (или продлить) рамки

Начну с секунду решение. Подумайте об использовании библиотеки FluentAssertions. Это позволяет сделать что-то вроде этого:

Action deleteUser =() => usersRepository.Delete(new User { Id = null }); 

deleteUser 
    .ShouldThrow<UserNotFoundException>() 
    .WithInnerException<ArgumentNullException>() 
    .WithInnerMessage("User Id must have value"); 

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

Первого выбор другой стороны, это немного больше работы, как это обычно бывает с самодельными решениями:

try 
{ 
    usersRepository.Delete(new User { Id = null }); 
    Assert.Fail("Deleting user with null id should throw"); 
} 
catch (UserNotFoundException ue) 
{ 
    Assert.AreEqual(ue.InnerException.Message, "User Id must have value"); 
} 

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

+0

Да, это должно быть так. Я просто хотел избежать расширения функциональности или использования внешних библиотек, но, похоже, это единственное возможное решение на данный момент. Спасибо. – zhulien

6

не полное решение, но в NUnit вы можете сделать такие вещи

var ex = Assert.Throws<Exception>(() => thing.ThatThrows()); 
Assert.That(ex.InnerException, Is.TypeOf<BadException>()); 

Может быть, вы можете в тестовых структурах?

+0

Как я уже сказал в комментарии к вопросу, структура VS не поддерживает метод Throws, и насколько мне известно, единственным возможным решением для «catching» исключений является использование этого атрибута. Может быть, я должен изменить код, чтобы бросить подробные исключения вместо вложенных изменений. – zhulien

1

Для модульного тестирования в настоящее время я использую FluentAssertions. Поскольку я узнал об этом, я никогда не хотел утверждать что-то другим.

Для утверждения исключения взглянуть на этом битый documentation

В частности, эта часть

Action act =() => subject.Foo2("Hello"); 

act.ShouldThrow<InvalidOperationException>() 
    .WithInnerException<ArgumentException>() 
    .WithInnerMessage("whatever") 
1

это старый вопрос, но я хочу поделиться своей собственной реализацией ExpectedInnerExceptionAttribute с вами, ребятами. может быть полезно кому-то

public class ExpectedInnerExceptionAttribute : ExpectedExceptionBaseAttribute 
{ 
    public ExpectedInnerExceptionAttribute(Type exceptionType) 
    { 
    this.ExceptionType = exceptionType; 
    } 

    public Type ExceptionType { get; private set; } 

    protected override void Verify(Exception ex) 
    { 
    if (ex != null && ex.InnerException != null 
      && ex.InnerException.GetType() == this.ExceptionType) 
     { 
     return; 
     } 

     throw ex; 
    } 
} 

Вы также можете расширить его, чтобы проверить сообщение об исключении и т. д. Вам просто нужно добавить свою собственную логику в метод Verify.

Смежные вопросы