2012-04-02 7 views
2

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

Во всяком случае, я знаю, что мне нужно попробовать/поймать, но как я могу проверить, что исключение поймано?

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

+0

Не ловить. Или, возможно, исключение. – Zenwalker

+0

Если исключение не обрабатывается блоком 'Catch', то ваш юнит-тест не будет выдавать какое-либо конкретное исключение, но если он будет проверен/обработан, ваш тест пройдет. Не уверен, есть ли какой-либо конкретный способ. – Rahul

+0

Утвердить исключение, тогда тестовый пример не завершится. – Zenwalker

ответ

3

Если вы делаете TDD, вы должны двигаться небольшими шагами и сосредоточиться на том, что классы должны делать. Вот пример. Вы хотите распечатать несколько отчетов. Сначала (я предполагаю, что вы двигаетесь за пределы) вы разрабатываете класс Report, который должен печатать себя через Printer (это только пример). Так вы пишете тест:

[Test] 
public void ShouldPrintItself() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>();    
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    report.Print(); 
    printer.Verify(p => p.Print("foo")); 
} 

И вы пишете какую-то реализацию report.Print метода. Также вы сейчас разрабатываете интерфейс IPrinter. Затем вы понимаете, что принтер иногда может показывать исключения (например, из бумаги). Это ваш случай кстати. Таким образом, вы переименовывать report.Print способ что-то вроде TryPrint, изменить первое испытание и создать новый:

[Test] 
public void ShouldPrint() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>();    
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    Assert.True(report.TryPrint()); 
    printer.Verify(p => p.Print("foo")); 
} 

[Test] 
public void ShouldNotPrint() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>(); 
    printer.Setup(p => p.Print(It.IsAny<string>())).Throws<Exception>(); 
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    Assert.False(report.TryPrint()); 
} 

И вы вернетесь к TryPrint методе. Теперь вы добавляете try catch блок вокруг вызова на принтер и сделать тесты пройдены (то же самое следует делать в вашем приложении):

public bool TryPrint() 
{ 
    try 
    { 
     _printer.Print(_text); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     // of course, log exception 
     return false; 
    }   
} 

Когда вы сделали здесь, вы можете перейти к созданию Printer. В вашем случае это будут тесты компонентов. Хорошие новости - у вас уже есть интерфейс IPrinter. Таким образом, вы пишете тесты и проверить, что в некоторых случаях будет сгенерировано исключение:

[Test] 
public void ShouldThrowExceptionWhenNoPaperLeft() 
{ 
    Printer printer = new Printer(); 
    printer.PagesCount = 0; 

    Exception ex = Assert.Throws<Exception>(() => printer.Print("foo")); 
    Assert.That(ex.Message, Is.EqualTo("Out of paper")); 
} 

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

1

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

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

+0

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

1

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

0

Это то, что я пошел с, но было бы интересно мнение людей:

[Test] 
public void DoSomething_NullParameterEntered_ShouldCatchException() 
{ 
    var component = new Whatever(); 

    try 
    { 
     component.DoSomething(null); //If a try/catch block exists it will not fall into the below catch 
    } 
    catch 
    { 
     Assert.Fail(); 
    } 
} 
+0

Если блок try/catch не существует, ваш тест в любом случае не удастся, поскольку исключение был брошен. Таким образом, вы просто пишете тест для 'DoSomething (null)' без try/catch. И вы пишете тесты, которые ожидают исключения из вашего компонента для 'DoSomething (not null)'. См. Мой пример ниже. –

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