Can I replace/upgrade Unity's NUnit?

What I want is Assert.ThrowsAsync so I can use it with the new .NET 4.6. However Unity’s NUnit does not have it.

I tried replacing nunit.framework.dll in Unity app folder inside Managed folder, delete Library folder of my game, let it rebuild, reimport all, etc. but still Assert.ThrowsAsync is not available. Any way to replace the shipped library?

3 Likes

I made my own ThrowsAssert, just in case anyone needs it. You can await on it.

public static class E7Assert
{
    public static async Task ThrowsAsync<T>(Task asyncMethod) where T : Exception
    {
        await ThrowsAsync<T>(asyncMethod,"");
    }

    public static async Task ThrowsAsync<T>(Task asyncMethod,string message) where T : Exception
    {
        try
        {
            await asyncMethod; //Should throw..
        }
        catch(T)
        {
            //Ok! Swallow the exception.
            return;
        }
        catch(Exception e)
        {
            if(message != "")
            {
                Assert.That(e, Is.TypeOf<T>(), message + " " + e.ToString()); //of course this fail because it goes through the first catch..
            }
            else
            {
                Assert.That(e, Is.TypeOf<T>(), e.ToString());
            }
            throw; //probably unreachable
        }
        Assert.Fail("Expected an exception of type " + typeof(T).FullName + " but no exception was thrown."  );
    }
}
5 Likes

I just hit this same problem 2 minutes ago. It’s baffling how in two years they haven’t updated their version of nunit.

Is there any plans to update in the future?

Also, thanks @5argon for the custom work around! I also read your article on async await in unity as well and it’s helped me a lot!

3 Likes

Thanks for the info, @5argon . I have created an alternative implementation, which has an API that mimics the NUnit-API:

public static TActual AssertThrowsAsync<TActual>(AsyncTestDelegate code, string message = "", params object[] args) where TActual : Exception
{
    return Assert.Throws<TActual>(() =>
    {
        try
        {
            code.Invoke().Wait(); // Will wrap any exceptions in an AggregateException
        }
        catch (AggregateException e)
        {
            if (e.InnerException is null)
            {
                throw;
            }
            throw e.InnerException; // Throw the unwrapped exception
        }
    }, message, args);
}

public delegate Task AsyncTestDelegate();
3 Likes

@EirikWahl Awesome, just what I needed, face the same problems, UniTask would have been the other alternative, but I didn’t want to add one more dependency to my in-house upm package. Thanks!

1 Like