考虑以下方法
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行为)。通常情况下,测试知道“four”应该失败,这就是它所关心的 - 失败。
这个例外(没有双关语)可能是将异常翻译成传递给用户的东西的情况,例如用户友好的消息(例如映射到UserNameTakenException >已经使用的用户名,尝试不同的)。在这种情况下,您需要确保传达正确的错误。即便如此,它也有一点问题,因为它会对每个可能的用户错误产生不同类型的异常,但这可能不会太糟糕(通常没有太多)。
我的思路是否有意义?我是否应该在不涉及面向用户的异常的测试用例中捕获通用Exception
?
答案 0 :(得分:3)
只需编写至少4个测试:
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void TestFooForNull()
{
Foo(null);
}
[Test]
[ExpectedException(typeof(MyException))]
public void TestFooForInvalidSizeTooShort()
{
Foo("1234");
}
[Test]
[ExpectedException(typeof(MyException))]
public void TestFooForInvalidSizeTooLong()
{
Foo("123456");
}
[Test]
public void TestFoo()
{
Foo("12345");
}
编写单元测试时,最好每次测试处理一个特定情况。
答案 1 :(得分:0)
> should I expect the exact exception?
> ...
> Should I indeed catch the generic Exception in test cases that
> don't involve user-facing exceptions ?
在dotnet中捕获泛型Exception
并不是一个好主意,因为它也会捕获AssertionException。我认为它与java相同
public void ThisTestWillNeverFail()
{
try
{
Assert.Fail("some error message");
}
catch (Exception)
{
}
}