2

考虑以下方法

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

2 回答 2

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");
}

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

于 2013-08-26T13:17:44.733 回答
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) 
    {
    } 
}
于 2013-08-26T15:09:55.940 回答