Nunit: Assert.Throws does not work with async delegates

Created on 12 Jan 2016  ·  9Comments  ·  Source: nunit/nunit

With this test case:

using System;
using System.Threading.Tasks;
using NUnit.Framework;

namespace NUnitAsync
{
    [TestFixture]
    public class Class1
    {
        [Test]
        public void MyAsyncThingTest()
        {
            var ioe = Assert.Throws<InvalidOperationException>(async () => await DelayedFailureAsync());
            Assert.That(ioe.Message, Is.EqualTo("ABC"));
        }

        [Test]
        public void MyAsyncThingFluentTest()
        {
            Assert.That(async () => await DelayedFailureAsync(), Throws.Exception.TypeOf<InvalidOperationException>().And.Message.EqualTo("ABC"));
        }

        static async Task DelayedFailureAsync()
        {
            await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
            throw new InvalidOperationException("ABC");
        }
    }
}

:negative_squared_cross_mark: MyAsyncThingTest fails with this exception:

Test Name:  MyAsyncThingTest
Test FullName:  NUnitAsync.Class1.MyAsyncThingTest
Test Source:    C:\Temp\NUnitAsync\NUnitAsync\Class1.cs : line 15
Test Outcome:   Failed
Test Duration:  0:00:00.004

Result StackTrace:  
at NUnit.Framework.Internal.AsyncInvocationRegion.Create(MethodInfo method)
   at NUnit.Framework.Assert.Throws(IResolveConstraint expression, TestDelegate code, String message, Object[] args)
   at NUnit.Framework.Assert.Throws[TActual](TestDelegate code, String message, Object[] args)
   at NUnit.Framework.Assert.Throws[TActual](TestDelegate code)
   at NUnitAsync.Class1.MyAsyncThingTest() in C:\Temp\NUnitAsync\NUnitAsync\Class1.cs:line 16
Result Message: System.ArgumentException : 'async void' methods are not supported, please use 'async Task' instead

:white_check_mark: MyAsyncThingFluentTest passes.

Why the difference? Assert.Throws returns the exception for further testing, which is useful functionality that the Assert.That style does not provide.

duplicate

Most helpful comment

Stackoverflow brought me here. Great work!! I updated in NuGet to the 3.20 version and could use the Assert.ThrowsAsyc function!

All 9 comments

Thanks for the report. I have confirmed and assigned this as a high priority issue. Both instances take a TestDelegate, so they should behave the same.

As for why Assert.That does not return the exception, it is because we don't know which constraint you are going to use based on the signature. It is common to write fluent asserts like Assert.That(async () => await One(), Is.EqualTo(1))); which is the same method that you are calling.

Interestingly, this appears to only be a problem with the throws constraint. Other constraints work,

``` C#
[Test]
public void TestTheMeaningOfLife()
{
Assert.That(async () => await DelayedMeaningOfLife(), Is.EqualTo(42));
}

static async Task DelayedMeaningOfLife()
{
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
return 42;
}
```

What do you mean by a problem with the throws constraint? Unless Assert.Throws uses that internally, the throws constraint (Assert.That(..., Throws...)) works. It's Assert.Throws that is not working.

If Assert.That works for Throws I'd expect it would also be working for Is.EqualTo and friends.

My mistake, I misread which test was failing and even misread which of my tests was failing. So my comment about the constraint is incorrect. Assert.Throws is one of the few classic asserts that doesn't chain to its equivalent constraint.

Fixed by #1142, but we will need to document.

Thanks.

I can't see from the changes to #1142, but does the error message ("async void methods are not supported") remain, or does the error indicate that the developer should be using Assert.ThrowsAsync instead?

@yaakov-h, yes, once we release the next version, Assert.ThrowsAsync should be used instead. For now, use the fluent syntax.

Stackoverflow brought me here. Great work!! I updated in NuGet to the 3.20 version and could use the Assert.ThrowsAsyc function!

Just what I was looking for. Thanks.

Was this page helpful?
0 / 5 - 0 ratings