86

So I have a test like the following:

[Fact]
public void Test1()
{
    Assert.ThrowsAsync<ArgumentNullException>(() => MethodThatThrows());
}

private async Task MethodThatThrows()
{
    await Task.Delay(100);
    throw new NotImplementedException();
}

To my surprise, Test1 passes successfully. To make it fail I have to write like this:

Assert.Throws<ArgumentNullException>(() => MethodThatThrows().Wait());

What is the purpose of ThrowsAsync(), if it does not work in the scenario above?

Ivan Gechev
  • 706
  • 3
  • 9
  • 21
Dmitry
  • 1,220
  • 2
  • 11
  • 18

2 Answers2

155

You're supposed to await the result (see xunit's acceptance tests for examples and alternate forms).

[Fact]
async void Test1()
{
    await Assert.ThrowsAsync<ArgumentNullException>(() => MethodThatThrows());
}

In this specific degenerate case, you could just return the Task that Assert.ThrowsAsync yields without using await; but in that case, the key thing is to yield the Task back to the xUnit framework, i.e.

[Fact]
Task Test1() =>
    Assert.ThrowsAsync<ArgumentNullException>(MethodThatThrows);
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
40

Just in case anyone wants to separate Act and Assert part, below code can be used:

//Act
Task result() => systemUnderTest.AsyncMethodThatThrows();

//Assert
await Assert.ThrowsAsync<Exception>(result); 
Saket Kumar
  • 4,363
  • 4
  • 32
  • 55