Test a function throwing an Exception in a Task in xunit

Viewed 531

I want to test using xunit a function that run a task and throw in a that task For example :

public void doSomething(){
     Task.Run(() =>
            {
                throw new ArgumentNullException();
            });
}

When I want to test this function by doing this :

[Fact]
public void TestIfTheMethodThrow()
{
   Assert.Throws<ArgumentNullException>(() => doSomething()); // should return true but return false                                                                   
}

I want that the Task.Run() finish completely then the assert can be done. anyone have a solution ?

2 Answers

Raising and handling exceptions using TPL (the Tasks library) is slightly different, than the "standard" exception handling. It is meaningful to evaluate only a completed task, so you need to wait for the completion, even if in this case it is an exception.

Have a look at this MSDN article Exception handling (Task Parallel Library).

You have two different options:

  • add .Wait() to the Task.Run(...)`

    Task.Run(() =>
           {
               throw new ArgumentNullException();
           }).Wait();
    
    
    
  • or wait while the task is completed while(!task.IsCompleted) {}

     var task = Task.Run(() =>
            {
                throw new ArgumentNullException();
            });
    while(!task.IsCompleted) {}

The test result should be then as expected - an exception is thrown.

It could be, that before the Wait your test has passed sporadically - don't be irritated - in this case the task execution was faster than the test check - this is a dangerous source of subtle errors.

You can write your method using async and await

Read this for reference Asynchronous programming with async and await

The new method look like this, and the caller will decide if want wait or not, if you call with await it will wait the task complete, otherwise it will continue without wait the task completion

public async Task DoSomethingAsync()
{
    if (true)
        throw new ArgumentNullException();
    await FooAsync();
}

In the test:

[Fact]
public async Task TestIfTheMethodThrow()
{
   await Assert.ThrowsAsync<ArgumentNullException>(() => DoSomethingAsync());                
}
Related