Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't Assert exception in async method with Xunit

Some mistake in a code test rise this question, due the extension of the code, here is a complete project that replicates exactly the problem we have (to save you analyzing tons of lines).

The issue is when trying to catch an exception from an asynchronous method, here the AsyncTest.cs file:

using System;
using Xunit;

namespace AsyncTest
{
    public class AsyncTest
    {
        [Fact]
        public void ProbeTest()
        {
            // Arrange
            var probe = new Probe();

            // Act
            Action action = async () =>
                await probe.GetJob();

            // Assert
            var ex = Assert.Throws<InvalidOperationException>(action);
            Assert.Contains("Trouble with Project.", ex.Message);
        }
    }
}

Now, the Probe.cs class to be tested (Note the delay and the exception throwing in GetById method called by the GetJob method):

using System;
using System.Threading.Tasks;

namespace AsyncTest
{
    class Probe
    {
        public async Task<MyResult<Guid>> GetJob()
        {
            var etlJob = await GetById("id");
            return new MyResult<Guid>(etlJob);
        }

        public async Task<Guid> GetById(string id)
        {
            await Task.Delay(200);

            throw new InvalidOperationException("Trouble with Project.");
        }
    }
}

Last, the MyResult.cs class used by Probe.cs.

namespace AsyncTest
{
    public class MyResult<T>
    {
        private T _value;

        public MyResult(T Value)
        {
            _value = Value;
        }

        public string Message { get; set; }
        public T Data { get; set; }
    }
}

Apparently, the test ends before the exception is thrown even if the await Task.Delay(200); line is removed. In some cases using multiple breakpoints and placing the call in a loop, an exception is throw but not detected by the test.

It looks like a synchronous and asynchronous mix-up but can't figure out exactly what.

Thanks in advance.

like image 891
TrustworthySystems Avatar asked May 26 '20 23:05

TrustworthySystems


1 Answers

Make your test method asynchronous and await the assertion:

[Fact]
public async Task ProbeTest()
{
    // Arrange
    var probe = new Probe();

    // Act
    Func<Task> action = async () => await probe.GetJob();

    // Assert
    var ex = await Assert.ThrowsAsync<InvalidOperationException>(action);
    Assert.Contains("Trouble with Project.", ex.Message);
}
like image 52
Guru Stron Avatar answered Oct 22 '22 10:10

Guru Stron