考虑以下方法
public void Foo(string str)
{
if (str == null)
throw new ArgumentNullException("str");
if (str.Length != 5)
throw new MyException();
}
假设我想为它写一个否定测试,如下所示:
public void TestFoo()
{
try
{
Foo(null); //this could be an remote call (e.g. WCF)
Assert.Fail("Expected ArgumentNullException");
}
catch (ArgumentNullException) {} //should this be "Exception" instead?
try
{
Foo("four"); //this could be an remote call (e.g. WCF)
Assert.Fail("Expected MyException");
}
catch (MyException) {} //should this be "Exception" instead?
}
在我看来,捕获上述特定异常是一个实现细节,这可能会使测试变得脆弱并且与实现(而不是接口)过于耦合。显然MyException
有一天可能会改变,但甚至ArgumentNullException
可能会被包装在其他一些异常中(例如,通过未来的 WCF 行为)。通常,测试知道“四”应该失败,这就是它所关心的——失败。
例外情况(没有双关语)可能是例外情况被翻译成传递给用户的东西,例如用户友好的消息(例如UserNameTakenException
,它映射到已经使用的用户名,尝试不同的) . 在这种情况下,您需要确保传达正确的错误。即便如此,它还是有点问题,因为这意味着每个可能的用户错误都会出现不同类型的异常,但这可能还不算太糟糕(通常这些错误并不多)。
我的思路有意义吗?我真的应该Exception
在不涉及面向用户的异常的测试用例中捕捉到泛型吗?