【问题标题】:How to test whether a ref struct method is throwing an exception using xUnit?如何使用 xUnit 测试 ref struct 方法是否抛出异常?
【发布时间】:2018-07-12 14:23:06
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c# xunit ref-struct


    【解决方案1】:

    不能在 lambda 表达式中捕获 ref struct,但您仍然可以在 lambda 表达式中使用 - 您只需要在此处声明变量,所以它永远不是非引用结构中的字段。

    比如这样编译成功:

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

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

    使用Assert.Throws 会有所帮助,这样只有预期的异常才会通过。此外,您可以捕获在投掷部分之前更改的bool,然后检查您是否已经完成了:

    [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 限制时要冗长得多,但它们是可以理解的......

    【讨论】:

    • @Trauer:查看更新;你可以更进一步。
    【解决方案2】:

    您可以实现自己的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));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 2021-10-28
      • 1970-01-01
      • 2018-12-10
      相关资源
      最近更新 更多