阴性测试——我应该期待确切的例外吗

本文关键字:期待 测试 我应该 | 更新日期: 2023-09-27 18:29:12

考虑以下方法

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吗?

阴性测试——我应该期待确切的例外吗

只需编写至少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");
}

在编写单元测试时,最好每个测试处理一个特定的案例。

  > 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) 
    {
    } 
}