Show / Hide Table of Contents

    Async Test

    Use Case

    When writing unit tests, you will encounter tests where asynchronous methods need to be awaited. With the NUnit version that is used in Unity, you can only create test methods that are either async void or IEnumerator coroutines for asynchronous processes. The usual way of awaiting a method call in an async Task method is not possible. You should not use async void methods as it can lead to unexpected behavior, especially if an exception is thrown (for a detailed explanation on why you should avoid async void, click here). Therefore, the i5 Toolkit provides an AsyncTest class. With the help of this class, the async methods are awaited inside of coroutines.

    Usage

    Async Methods Without Return Value

    In this example, a test must await the async method FooAsync(). Create a [UnityTest] unit test which can run over multiple frames. This means that the return type of this test method needs to be IEnumerator. After that write the test. Instead of adding await FooAsync(), first create a Task object from the method call. After that, use WaitForTask to execute the task:

    [UnityTest]
    public IEnumerator MyAsyncUnitTest()
    {
        ...
        // first create a task object
        // note that this does not execute the method directly
        Task task = FooAsync();
        // execute the task inside of the WaitForTask coroutine
        yield return AsyncTest.WaitForTask(task);
    
        Debug.Log("This log is only printed once the async task has finished");
    }
    

    Async Methods With Return Value

    Write the test in the same way as in the example without a return value. Instead of using Task, use the variant Task<TResult>. This class takes a generic type which defines the result's type. After the completion of a task, the task object contains the result in its Result property.

    [UnityTest]
    public IEnumerator MyAsyncUnitTest()
    {
        ...
        // first create a task object
        // note that this does not execute the method directly
        Task<int> task = FooReturnValueAsync();
        // execute the task inside of the WaitForTask coroutine
        yield return AsyncTest.WaitForTask(task);
    
        Debug.Log("The result is: " + task.Result);
    }
    

    Functionality

    WaitForTask executes the given task in a coroutine and waits for it to complete. After that, the result is available in the task object. The coroutine of the test function waits for the WaitForTask method to finish. If an exception is thrown during the execution of the async method, WaitForTask will re-throw this exception. This cirumvents the problem that exceptions in coroutines occur silently.

    • Improve this Doc
    Back to top i5 Toolkit Documentation