Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assert.Throws does not work with async delegates #1190

Closed
yaakov-h opened this issue Jan 12, 2016 · 9 comments
Closed

Assert.Throws does not work with async delegates #1190

yaakov-h opened this issue Jan 12, 2016 · 9 comments

Comments

@yaakov-h
Copy link
Contributor

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");
        }
    }
}

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

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.

@rprouse rprouse added this to the Backlog milestone Jan 15, 2016
@rprouse
Copy link
Member

rprouse commented Jan 15, 2016

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.

@rprouse
Copy link
Member

rprouse commented Jan 15, 2016

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

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

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

rprouse added a commit to rprouse/nunit-tests that referenced this issue Jan 15, 2016
@yaakov-h
Copy link
Contributor Author

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.

@rprouse
Copy link
Member

rprouse commented Jan 17, 2016

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.

@rprouse
Copy link
Member

rprouse commented Jan 20, 2016

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

@yaakov-h
Copy link
Contributor Author

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?

@rprouse
Copy link
Member

rprouse commented Jan 20, 2016

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

@rprouse rprouse modified the milestone: Backlog Jan 25, 2016
@bartvanderwal
Copy link

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

@gwin003
Copy link

gwin003 commented Sep 7, 2016

Just what I was looking for. Thanks.

@rprouse rprouse modified the milestone: Closed Without Action Jan 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants