Hello.
I just joined the group, so a few words about myself: I am a professional C# developer using NUnit, but I have little experience in contributing to open source projects.
The issue at hand: Lately I've been working a mostly with
ASP.NET Web Api 2 and dealing with a lot of async code. A lot of my unit tests are checking if async functions are throwing proper exceptions (or not throwing them). This is related to
https://github.com/nunit/nunit/issues/464 issue on NUnit's GitHub page. From this post I understand that this feature has been scheduled for version 3.2 of NUnit. Meanwhile, I've written a following wrapper for my own use (some stuff I just copied from NUnit's source):
using System;
using System.Threading.Tasks;
namespace Nunit.Framework.Async
{
using NUnit.Framework;
using NUnit.Framework.Constraints;
using NUnit.Framework.Internal;
public delegate Task TestDelegateAsync();
public static class AssertAsync
{
public static async Task DoesNotThrowAsync(TestDelegateAsync testDelegateAsync)
{
// ReSharper disable once CatchAllClause
try
{
await testDelegateAsync.Invoke();
}
catch (Exception ex)
{
var result =
new ConstraintResult(constraint: new ThrowsNothingConstraint(), actualValue: ex, isSuccess: false);
MessageWriter writer = new TextMessageWriter();
result.WriteMessageTo(writer);
throw new AssertionException(writer.ToString());
}
TestExecutionContext.CurrentContext.IncrementAssertCount();
}
public static async Task<TActual> ThrowsAsync<TActual>(TestDelegateAsync testDelegateAsync)
where TActual : Exception
{
Exception caughtException = null;
// ReSharper disable once CatchAllClause
try
{
await testDelegateAsync.Invoke();
}
catch (Exception ex)
{
caughtException = ex;
}
Assert.That(caughtException, new ExceptionTypeConstraint(typeof (TActual)), string.Empty, null);
return (TActual) caughtException;
}
}
}
What I would like to ask is if this is the right approach and what problems can you guys immediately see from using it this way. Here's an example of usage:
using System;
using System.Threading.Tasks;
namespace Sut
{
public class Sut
{
public async Task ThrowingException()
{
throw new Exception();
}
public async Task NotThrowingException()
{
}
}
}
namespace SutTests
{
using Sut;
using NUnit.Framework;
using Nunit.Framework.Async;
[TestFixture]
public class AsyncTests
{
[Test]
public async Task ThrowingException_ThrowsException()
{
var sut = new Sut();
TestDelegateAsync td = async () => await sut.ThrowingException();
Exception ex = await AssertAsync.ThrowsAsync<Exception>(td);
}
[Test]
public async Task NotThrowingException_DoesNotThrowException()
{
var sut = new Sut();
TestDelegateAsync td = async () => await sut.NotThrowingException();
await AssertAsync.DoesNotThrowAsync(td);
}
/// <summary>
/// An example of a failing test.
/// </summary>
[Test]
public async Task ThrowingException_DoesNotThrowException()
{
var sut = new Sut();
TestDelegateAsync td = async () => await sut.ThrowingException();
await AssertAsync.DoesNotThrowAsync(td);
}
/// <summary>
/// An example of a failing test.
/// </summary>
[Test]
public async Task NotThrowingException_ThrowsException()
{
var sut = new Sut();
TestDelegateAsync td = async () => await sut.NotThrowingException();
Exception ex = await AssertAsync.ThrowsAsync<Exception>(td);
}
}
}
In case there's no one yet assigned to this issue, and if it make sense, please let me know. I'd be interested in expanding the implementation for other Throws() overloads, but maybe I'm completely missing a point here?
Thanks in advance for your time and consideration.
Best regards,
Piotr