Search code examples
c#xunitref-struct

How to test whether a ref struct method is throwing an exception using xUnit?


I'm new to xUnit, but, as far as I know, the standard way of checking whether something throws an exception is to use Assert.Throws<T> or Assert.ThrowsAny<T> methods.

But these methods expect an Action as parameter; and ref structs can't be "embedded" in lambdas.

So, how does one test whether a given method of a ref struct is throwing? Example of code that doesn't work:

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

Solution

  • A ref struct can't be captured in a lambda expression, but you can still use it in a lambda expression - you just need to declare the variable there, so that it's never a field within a non-ref-struct.

    For example, this compiles and succeeds:

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

    Now I'll be the first to admit that this isn't ideal: you really want to do the minimum amount of work possible within the action, so that you only pass if the expected piece of code fails.

    Using Assert.Throws helps there, so that only the expected exception results in a pass. Additionally, you could capture a bool which is changed just before the throwing part, then check that you'd got that far:

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

    It's all significantly wordier than it would be if it weren't for ref struct restrictions, but they're understandable...