# NSubstitute - make async method (Task) throw an exception


The other day I was writing a unit test to verify what was supposed to happen when a `Task` would throw an exception when awaited. It wasn't as straight forward as I first assumed, but I quickly found this Stack Overflow post that helped me:

%[https://stackoverflow.com/questions/38338906/nsubstitute-mock-throwing-an-exception-in-method-returning-task]

Normally, for synchronous calls, you can just add a `.Throws<TException>()` after the method you want to mock throwing an exception (or `.ThrowsForAnyArgs<TException>()` if you don't care about the input arguments). If you do this on a method returning a `Task` then that call would instantly throw, which is - most often - not what happens; it's the work being done by the `Task` throwing an exception, not the action of creating the `Task`.

As you can read in the Stack Overflow post the way to simulate a `Task` throwing an exception is to have the method return an already faulted `Task`, which can be done (sort of easily) with the static method `Task.FromException<TReturn>(Exception)`.

```csharp
interface IService
{
    Task<MyModel> GetAsync();
}
```

```csharp
var service = Substitute.For<IService>();
service.GetAsync().Returns(Task.FromException<MyModel>(new ArgumentException("bla bla"));
```

But that's a bit too verbose for my taste, compared to this synchronous version:

```csharp
var service = Substitute.For<IService>();
service.Get().Throws<ArgumentException>();
```

So I ended up creating a few extension methods enabling a more simple and readable syntax, so I could instead write it like this:

```csharp
var service = Substitute.For<IService>();

// Any Exception
service.GetAsync().TaskThrowsException("optional message");

// Specific Exception v1
service.GetAsync().TaskThrows<MyModel, ArgumentException>("optional message");
// Specific Exception v2
service.GetAsync().TaskThrows(typeof(ArgumentException), "optional message");

// Specific Exception instance
service.GetAsync().TaskThrows(new ArgumentException());
```

That's a lot cleaner and more readable in my eyes :)

The `TaskThrows<MyModel, ArgumentException>()` might seem a little weird, but for the generic `Task<T>` we sadly can't have the generic arguments inferred as we can for the others :(

Here are all the extension methods for both `Task` and `Task<T>`:

```csharp
public static class NSubstituteExtensions
{
    public static ConfiguredCall TaskThrowsException<T>(this Task<T> task, string message = null)
    {
        return TaskThrows<T, Exception>(task, message);
    }

    public static ConfiguredCall TaskThrows<T, TException>(this Task<T> task, string message = null)
        where TException : Exception
    {
        return TaskThrows(task, typeof(TException));
    }

    public static ConfiguredCall TaskThrows<T>(this Task<T> task, Type exceptionType, string message = null)
    {
        if (!typeof(Exception).IsAssignableFrom(exceptionType))
            throw new ArgumentException($"Type has to be a subclass of System.Exception", nameof(exceptionType));
        
        var exception = Activator.CreateInstance(exceptionType, message) as Exception;
        return TaskThrows(task, exception);
    }

    public static ConfiguredCall TaskThrows<T>(this Task<T> task, Exception exception)
    {
        return task.Returns(Task.FromException<T>(exception));
    }

    public static ConfiguredCall TaskThrows<TException>(this Task task, string message = null)
        where TException : Exception
    {
        return TaskThrows(task, typeof(TException));
    }

    public static ConfiguredCall TaskThrows(this Task task, Type exceptionType, string message = null)
    {
        if (!typeof(Exception).IsAssignableFrom(exceptionType))
            throw new ArgumentException($"Type has to be a subclass of System.Exception", nameof(exceptionType));

        var exception = Activator.CreateInstance(exceptionType, message) as Exception;
        return TaskThrows(task, exception);
    }

    public static ConfiguredCall TaskThrows(this Task task, Exception exception)
    {
        return task.Returns(Task.FromException(exception));
    }
}
```
