- Home /
Async unit test in Test Runner
Is it possible to unit test async functions? I can't get it to work.
If I use 'async void', the test always passes, even if the assertion fails. If I use 'async Task', I can't run the test. Unity Test Runner reports: "Method has non-void return value, but no result is expected".
[Test]
public async void MyTestFailAsyncVoid()
{
await Task.Delay(1000);
Assert.That(false);
}
[Test]
public async Task MyTestFailAsyncTask()
{
await Task.Delay(1000);
Assert.That(false);
}
Answer by MathijsF · May 28, 2019 at 10:06 AM
In case anybody else cares about this, we found a workaround of sorts.
It uses the 'Async Await Support' library on the Unity Store: link . We added a function to the library to have AsIEnumerator() return null:
public static IEnumerator AsIEnumeratorReturnNull<T>(this Task<T> task)
{
while (!task.IsCompleted)
{
yield return null;
}
if (task.IsFaulted)
{
ExceptionDispatchInfo.Capture(task.Exception).Throw();
}
yield return null;
}
An async test looks like this:
[UnityTest]
public IEnumerator MyAsyncTest()
{
var task = MyObject.SomeAsyncCall();
yield return task.AsIEnumeratorReturnNull();
var returnValue = task.Result;
Assert.AreEqual(expectedReturnValue, returnValue);
}
An async test that should throw an exception looks like this:
[UnityTest]
public IEnumerator MyAsyncTestThatShouldThrow()
{
async Task<bool> FailsWithException()
{
try
{
await MyObject.SomeAsyncCall();
}
catch (Exception)
{
return true;
}
return false;
}
var task = FailsWithException();
yield return task.AsIEnumerator();
var threwException = task.Result;
Assert.That(threwException);
}
Answer by AlexStark_ · Jul 02, 2020 at 07:52 AM
Based on this thread https://forum.unity.com/threads/async-await-in-unittests.513857/#post-6046400 You can use the following helpers
public static class UnityTestUtils {
public static T RunAsyncMethodSync<T>(Func<Task<T>> asyncFunc) {
return Task.Run(async () => await asyncFunc()).GetAwaiter().GetResult();
}
public static void RunAsyncMethodSync(Func<Task> asyncFunc) {
Task.Run(async () => await asyncFunc()).GetAwaiter().GetResult();
}
}
Usage:
[Test]
public void Test()
{
var result = RunAsyncMethodSync(() => GetTestTaskAsync(4));
Assert.That(result, Is.EqualTo(4));
}
public async Task<int> GetTestTaskAsync(int a) {
await Task.Delay(TimeSpan.FromMilliseconds(200));
return a;
}
[Test]
public void Testthrow() {
Assert.Throws<InvalidOperationException>(
()=> RunAsyncMethodSync(() => ThrowTaskAsync(4)));
}
public async Task<int> ThrowTaskAsync(int a) {
await Task.Delay(TimeSpan.FromMilliseconds(200));
throw new InvalidOperationException();
}
Answer by ochir_d · May 25, 2021 at 12:37 AM
Utils
public static class UnityTestUtils {
public static void RunAsyncMethodSync(this Func < Task > asyncFunc) {
Task.Run(async () => await asyncFunc()).GetAwaiter().GetResult();
}
}
Usage
public class AsyncAwaitUnitTests {
[Test]
public void WithExt([Values(0, 500, 1000)] int delay) {
UnityTestUtils.RunAsyncMethodSync(async () => {
var sw = Stopwatch.StartNew();
await Task.Delay(delay);
Assert.AreEqual(delay, (int) sw.Elapsed.TotalMilliseconds, 300);
});
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220612190919im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
assetBundle - get the list of the assets in the bundle 5 Answers
LoadLevelAsync movie not playing gui!! 1 Answer
Got a problem with Async! 0 Answers
Unity TCP async functions 0 Answers
Debugging async methods crashes editor 0 Answers