我有一个需要try / catch的方法。这是因为该方法是从Task
调用的。如果抛出异常,则线程将结束。我可以使用Task.ContinueWith
来处理错误,然后在发生错误的情况下启动一个新任务,但是try / catch可以解决这个问题。
无论如何,我知道我需要放一个try / catch但是如何测试异常被捕获?
我可以做的一种方法是引发一个接受字符串参数的现有事件,然后在单元测试中测试该字符串是否匹配我期望的字符串。不确定这是好还是不好但是想知道处理这种情况的最佳方法是什么。
答案 0 :(得分: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 :(得分:1)
你添加一个try / catch意味着当被测试的类调用另一个抛出异常时你有所需的行为。 try / catch是“如何”,测试行为。
因此,使用模拟,在调用“其他”服务时抛出异常,并测试您的类是否满足要求。首先编写测试,这将使您想到为什么要放入try / catch。
答案 2 :(得分:1)
您应该测试应用程序实际正在执行的 ,而不是如何。因此,只需模拟您的任务以抛出异常,并验证在这种情况下是否引发了新任务。
答案 3 :(得分: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();
}
}