10

我是 xUnit 的新手,但据我所知,检查某事是否引发异常的标准方法是使用Assert.Throws<T>Assert.ThrowsAny<T>方法。

但是这些方法需要一个 Action 作为参数;并且 ref 结构不能“嵌入”在 lambda 中。

那么,如何测试 ref 结构的给定方法是否正在抛出?不起作用的代码示例:

[Fact]
public void HelpMe() {
    var pls = new Span<byte>();
    Assert.ThrowsAny<Exception>(() => {
        plsExplode = pls[-1];
    });
}
4

2 回答 2

10

无法在 lambda 表达式中捕获ref struct ,但您仍然可以在 lambda 表达式中使用它 - 您只需在此处声明变量,这样它就不会是非 ref-struct 中的字段。

例如,这编译并成功:

[Fact]
public void HelpMe()
{
    Assert.ThrowsAny<Exception>(() => {
        var pls = new Span<byte>();
        var plsExplode = pls[-1];
    });
}

现在我将第一个承认这并不理想:您确实希望在操作中做尽可能少的工作,以便仅在预期的代码段失败时通过。

在那里使用Assert.Throws有帮助,因此只有预期的异常会导致通过。此外,您可以捕获bool在投掷部分之前更改的 a,然后检查您是否已经做到了:

[Fact]
public void HelpMe()
{
    bool reachedThrowingPart = false;
    Assert.Throws<IndexOutOfRangeException>(() =>
    {
        var span = new Span<byte>();
        reachedThrowingPart = true;
        var ignored = span[-1];
    });
    Assert.True(reachedThrowingPart);
}

这一切都比没有 ref struct 限制的情况要冗长得多,但它们是可以理解的......

于 2018-07-12T14:27:35.467 回答
0

您可以实现自己的Assert.Throws传递ref struct参数以避免在闭包中捕获它。

using System;
using Xunit;

public ref struct RefStruct1
{
    public void MethodThatThrows(int x) => throw new NotImplementedException();
}

public class Test1
{
    [Theory]
    [InlineData(0)]
    [InlineData(int.MaxValue)]
    public void MethodThatThrows_Always_ThrowsNotImplementedException(int x)
    {
        var refStruct1 = new RefStruct1();

        AssertThrows<NotImplementedException>(ref refStruct1, (ref RefStruct1 rs1) => rs1.MethodThatThrows(x));
    }

    private delegate void RefStruct1Action(ref RefStruct1 rs1);

    [System.Diagnostics.DebuggerStepThrough]
    private static T AssertThrows<T>(ref RefStruct1 rs1, RefStruct1Action action)
        where T : Exception
    {
        if (action == null)
            throw new ArgumentNullException(nameof(action));

        try
        {
            action(ref rs1);
        }
        catch (Exception ex)
        {
            if (ex.GetType() == typeof(T))
                return (T)ex;

            throw new Xunit.Sdk.ThrowsException(typeof(T), ex);
        }

        throw new Xunit.Sdk.ThrowsException(typeof(T));
    }
}
于 2019-04-02T05:20:16.367 回答