14

在某些情况下,我不在乎抛出什么异常(只要抛出一些异常)。很遗憾,

Assert.Throws<Exception>(someDelegate);

Exception除非恰好抛出了(因此不是派生类的实例)的实例,否则不会通过。我知道我可以得到我想要的行为

Exception exception = Record.Exception(someDelegate);
Assert.NotNull(exception);

但它不正确。我是否在 xUnit 中遗漏了具有我想要的行为的东西?这里有两个测试表明我的意思:

[Fact]
public void Throws_exception_and_passes() {
    Exception exception = Record.Exception(
        () => { throw new InvalidOperationException(); }
    );
    Assert.NotNull(exception);
}

[Fact]
public void Throws_exception_and_fails() {
    Assert.Throws<Exception>(
        () => { throw new InvalidOperationException(); }
    );
}
4

6 回答 6

8

根据此处的文档:

http://xunit.codeplex.com/wikipage?title=HowToUse&referringTitle=Home

您必须指定要抛出的异常类型。一般来说,这是一种很好的做法。您应该能够预测测试会在什么场景下抛出什么类型的异常。您应该能够以允许您预测这一点的方式设计您的方法和测试。

有一些方法可以解决这个问题,比如自己尝试一下,但你应该考虑改变你的设计。

于 2010-12-15T14:55:35.180 回答
5

在提出这个问题时它还不存在,但现在可以使用它Assert.ThrowsAny<Exception>来测试任何派生自的异常Exception(以及任何异常),以及诸如Assert.ThrowsAny<ArgumentException>which 将测试派生自的任何异常等变体ArgumentException

于 2015-09-08T23:54:43.400 回答
2

如果您想做自己的自定义断言,xUnit 不会妨碍您,例如:

public static bool Throws<T>(this Action action, bool discardExceptions = false) 
    where T : Exception
{
    try
    {
        action.Invoke();
    }
    catch (T)
    {
        return true;
    }
    catch (Exception)
    {
        if (discardExceptions)
        {
            return false;
        }
        throw;
    }
    return false;
}

或者:

public static bool Throws(this Action action)
{
    try
    {
        action.Invoke();
    }
    catch (Exception)
    {
       return true;
    }
    return false;
}
于 2010-12-15T15:00:33.107 回答
2

正如您所确定的,如果Assert.Throws<T>不符合要求,xUnit 中唯一剩下的 OOTB 就是使用Record.Exception.

正如您所确定的,执行“断言抛出任何东西”的主要方法是

Assert.NotNull( Record.Exception( lambda ))

看看它——不漂亮。这很可能是设计使然;xUnit.net 中很少有东西是偶然的(与经过仔细考虑的固执设计相反)。

Record.Exception出于某种原因返回结果(如果您使用 F#,则必须|> ignore丢弃该值)。您应该始终能够Assert了解正在发生的异常的性质,这样当您随着时间的推移更改代码时,您的代码中的实际问题不会被偶然忽略,这就是首先进行所有这些测试的原因地方。也许这可能采取以下形式

var exception = Record.Exception( sut.Something );
Assert.True( typeof(SomeException).IsAssignableFrom( exception ) );

看着那个, a 更安全Assert.NotNull(),但仍然感觉不对。正如GOOS中所讨论的,是时候倾听你的测试了(如果是自以为是的测试框架,那就是你的测试框架)。


但是,您问题中最大的问题是,在真实测试的真实示例中,总有一种方法可以使您的界面更清晰或以另一种方式表达您的期望,因此真正的答案是Mu

于 2013-07-20T07:50:25.393 回答
1

我只是在查看xUnit.net 源代码,这是罪魁祸首:

private static Exception Throws(Type exceptionType, Exception exception)
{
    Guard.ArgumentNotNull("exceptionType", exceptionType);

    if (exception == null)
        throw new ThrowsException(exceptionType);

    if (!exceptionType.Equals(exception.GetType()))
        throw new ThrowsException(exceptionType, exception);

    return exception;
}

如果应用此更改,可以解决您的问题:

if(!exceptionType.Equals(exception.GetType()))

至:

if(!exception.GetType().IsAssignableTo(exceptionType))

你可以提议提交补丁吗?

于 2013-08-19T15:20:15.720 回答
0
    public static void SuppressException<TSut>(this TSut value, Action<TSut> action) where TSut : class
    {
        try
        {
            action.Invoke(value);
        }
        catch (Exception)
        {
            //do nothing
        }
    }
于 2016-01-20T04:16:06.690 回答