否定测试 - 我应该期待确切的例外吗?

时间:2013-08-26 13:06:39

标签: c# testing

考虑以下方法

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

2 个答案:

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