忽略 xUnit.net 中的异常

发布于 2024-10-07 17:14:54 字数 708 浏览 0 评论 0原文

在某些情况下,我不在乎抛出什么异常(只要抛出一些异常)。不幸的是,

Assert.Throws<Exception>(someDelegate);

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

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

I have some cases where I don't care what exception is thrown (as long as some exception is thrown). Unfortunately,

Assert.Throws<Exception>(someDelegate);

doesn't pass unless exactly an instance of Exception (so not an instance of a derived class) is thrown. I know I can obtain the behavior I want with

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

but it doesn't read right. Am I missing something in xUnit that has the behavior I want? Here are two tests that indicate what I mean:

[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(); }
    );
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

江南月 2024-10-14 17:14:54

根据此处的文档:

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

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

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

Per the documentation here:

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

You have to specify the type of exception you want to be thrown. In general, this is good practice. You should be able to predict what scenarios a test would throw what type of exception. You should be able to design both you method and your test in a way that will allow you to predict this.

There are ways around this, like doing a try catch yourself, but you should look into changing your design a bit.

秋意浓 2024-10-14 17:14:54

在提出这个问题时它并不存在,但现在可以使用 Assert.ThrowsAny 来测试从 Exception 派生的任何异常(以及因此的任何异常)全部),以及诸如 Assert.ThrowsAny 之类的变体,这些变体将测试从 ArgumentException 派生的任何异常等。

It didn't exist at the time of this question, but now one can use Assert.ThrowsAny<Exception> to test for any exception derived from Exception (and hence any exception at all), along with variants such as Assert.ThrowsAny<ArgumentException> which would test for any exception derived from ArgumentException and so on.

友欢 2024-10-14 17:14:54

正如您已经确定的那样,如果 Assert.Throws 不符合要求,那么 xUnit 中唯一剩下的 OOTB 就是使用 Record.Exception

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

Assert.NotNull( Record.Exception( lambda ))

看它 - 不太漂亮。这可能是设计使然; xUnit.net 中很少有东西是偶然的(而不是经过深思熟虑的固执己见的设计)。

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

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

看看,它比 Assert.NotNull() 更安全,但仍然感觉不对。正如 GOOS 中所述,是时候聆听您的测试了 (如果是固执己见的测试框架,则为您的测试框架)。


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

As you've identified if Assert.Throws<T> doesn't fit the bill, the only OOTB thing in xUnit you're left with is using Record.Exception.

As you've identified, the main way of doing a 'Assert throws anything` is to do

Assert.NotNull( Record.Exception( lambda ))

Look at it - not pretty. This is likely by design; there are very few things in xUnit.net that are by accident (as opposed to carefully considered opinionated design).

Record.Exception returns a result for a reason (and if you were using F#, you'd have to |> ignore to chuck away the value). You should always be able to Assert something about the nature of the Exception that's happening so that an actual problem in your code doesn't get ignored by chance as you change your code over time, which is the reason for all this testing stuff in the first place. Perhaps that might take the form of

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

Looking at that, it's safer that an Assert.NotNull(), but still doesn't feel right. It's time to, as discussed in GOOS, listen to your tests (and in the case of an opinionated test framework, your test framework).


The biggest problem in your question is however that in a real example from a real test, there is always a way to make your interface clearer or express your expectation in another way, so the real answer is Mu.

骄傲 2024-10-14 17:14:54

如果您想执行自己的自定义断言,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;
}

xUnit won't stand in your way if you want to do your own Custom Assertion, something like:

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

Or:

public static bool Throws(this Action action)
{
    try
    {
        action.Invoke();
    }
    catch (Exception)
    {
       return true;
    }
    return false;
}
甜是你 2024-10-14 17:14:54

我只是在查看 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))

可以提出提交补丁吗?

I was just looking in the xUnit.net source and here is the culprit:

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

What would solve your problem is if this change were applied:

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

to:

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

You could possibly offer to submit a patch?

梦回梦里 2024-10-14 17:14:54
    public static void SuppressException<TSut>(this TSut value, Action<TSut> action) where TSut : class
    {
        try
        {
            action.Invoke(value);
        }
        catch (Exception)
        {
            //do nothing
        }
    }
    public static void SuppressException<TSut>(this TSut value, Action<TSut> action) where TSut : class
    {
        try
        {
            action.Invoke(value);
        }
        catch (Exception)
        {
            //do nothing
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文