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