Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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];
    });
}
like image 737
Trauer Avatar asked Jul 12 '18 14:07

Trauer


People also ask

How to check if a method call throws an exception in xUnit?

You can check if a method call throws an exception by using the Assert.Throws method from xUnit. This can be seen below: If the method SomethingThatThrowsAnException () from the above throws an exception the assertion passes, if it does not throw an exception, the assertion will fail and thereby the test fails. It is as simple as that.

How do you assert if a method actually throws an exception?

In this post I show how you can assert if a method actually throws an exception. xUnit is a popular testing framework for C# and .Net. You can check if a method call throws an exception by using the Assert.Throws method from xUnit. This can be seen below: Assert.Throws<Exception>(() => SomethingThatThrowsAnException());

What is a class fixture in xUnit?

The class fixture is a xUnit feature that allows you to share an object instance among all tests in a test class. In this case, the shared object is an instance of the WebApplicationFactory class provided by the Microsoft.

How do you test if a code throws an exception?

There seems to be two ways to go about this. One is to implicitly check for DoesNotThrow by letting the code not throw an exception and the test therefore passes, if the code throws an exception the test will fail, like it will with any uncaught exception.


Video Answer


1 Answers

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...

like image 156
Jon Skeet Avatar answered Oct 23 '22 19:10

Jon Skeet