Unit Testing a "Catch" in C# - c#

I have created an API project using .NET 6.0.
I have configured the app.MapGet method correctly, and they are executing their respective methods.
These methods execute their respective Datacalls and return "Results.Ok(results)"
public static class ResultSetBeingReturned
{
public static async Task<IResult> ExecuteResultSet<T>(this Task<IEnumerable<T>> task)
{
try
{
var results = await task;
if (results == null) return Results.NotFound();
return Results.Ok(results);
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
}
}
I want to unit test this method, so my question is: How do I invoke an API that is going to generate an Exception that is NOT a 404 Not Found?

By using an IEnumerable<T> which throws an exception in your tests:
public static async Task Main()
{
var enumerable = Task.Run(() => Error());
var res = await enumerable.ExecuteResultSet();
Console.WriteLine(res.GetType().Name); // whatever Result.Problem returns
}
private static IEnumerable<string> Error()
{
throw new Exception();
}
Live example: https://dotnetfiddle.net/FDT8fs
Another option is simply to use Task.FromException
public static async Task Main()
{
var res = await Task.FromException<IEnumerable<string>>(new Exception()).ExecuteResultSet();
Console.WriteLine(res.GetType().Name);
}
Live example: https://dotnetfiddle.net/oezJwI

Related

Encapsulate async method in Func<T>

First, i hope the title is okay.
I have a Grpc Client with the well known greeter service and try to encapsulate the SayHelloAsync call in a Func.
But the => operator is redlined because he can not convert the expression he say.
It works if i remove any async/await.
Its probably because SayHelloAsync returns AsyncUnaryCall(which have an awaiter) instead of Task but at the end its
not a Grpc issue i guess, its just my missunderstanding.
Here is my try:
static async Task Main()
{
var client = CreateGreeterClient();
await UnsafeTask<Service.HelloReply>(async () =>
{
var result = await client.SayHelloAsync(new Service.HelloRequest { Name = greeter.Name });
return Task<Service.HelloReply>.FromResult(result);
});
Console.ReadKey();
}
static async Task<T> UnsafeTask<T>(Func<AsyncUnaryCall<T>> method) where T:class
{
try
{
return await method();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return null;
}
}
Any tip would be greatful.

Awaiting manually created task is freezing ASP.NET app

I've made a queue, which contains tasks to do. After creating some tasks manually with new Task() in Returns method, my whole application hangs - await current;. The body of the task is not even triggered.
ConfigureAwait(false) didn't help.
The first task in the queue, which is not created by me, but other framework is executing successfully and returning a value. Mine - doesn't. I've tried add Task.CompletedTask and then it has worked. I don't understand why I can't even reach the body of the task containing _output assignment.
IDE debugger code screenshot
---UPDATE---
The code works when I use code below. With await it doesn't. Any ideas?
current.Start();
current.Wait();
Original code
private readonly Queue<Task> _pipe;
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(new Task(() => // this task causes a problem and breakpoint isn't hit inside
{
_output = outputBuilder(_results);
}));
return this;
}
public async Task<TOutput> Execute()
{
Task current;
while (_pipe.TryDequeue(out current))
{
if (current.IsCommandExecution())
{
IExecutionResult result = await (Task<IExecutionResult>)current; // this awaits successfully
_results.Add(result);
}
else
{
await current; // hangs here
}
}
return await Task.FromResult(_output);
}
Usage
[HttpGet("eventflow/pipe/issue/add/{title}")]
public async Task<IActionResult> PipeAction(string title)
=> Ok(
await Pipe<IExecutionResult>()
.Validate(title)
.Handle<AddIssueCommand>(IssueId.New, title)
.Returns(results => results.First())
.Execute());
You should never use the Task constructor. This goes double on ASP.NET, since constructed tasks are always Delegate Tasks, which interfere with the ASP.NET usage of the thread pool. The actual reason that the await hangs is because manually-created tasks need to be started.
If you have synchronous work that you need to wrap into a Task to work alongside asynchronous tasks, then you should use Task.CompletedTask and Task.FromException:
private static Task SynchronousWork(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
try { _output = outputBuilder(_results); return Task.CompletedTask; }
catch (Exception ex) { return Task.FromException(ex); }
}
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(SynchronousWork(outputBuilder));
return this;
}
However, note that this executes outputBuilder immediately, which may not be desirable due to its side effects on _results and _output. If you want a delayed execution queue, then the type in the queue needs to be changed from Task to Func<Task>. Then you can add to it as such:
public IPipeBuilder<TOutput> Returns(Func<IEnumerable<IExecutionResult>, TOutput> outputBuilder)
{
_pipe.Enqueue(() =>
{
try { _output = outputBuilder(_results); return Task.CompletedTask; }
catch (Exception ex) { return Task.FromException(ex); }
});
return this;
}
and you would consume it by calling each delegate one at a time and inspecting the task it returns:
public async Task<TOutput> Execute()
{
while (_pipe.TryDequeue(out var currentFunc))
{
var currentTask = currentFunc();
if (currentTask.IsCommandExecution())
{
IExecutionResult result = await (Task<IExecutionResult>)currentTask;
_results.Add(result);
}
else
{
await currentTask;
}
}
return _output;
}
Okay, thank you. I've ended up with such class and Queue<Func<Task>> like you said.
public sealed class SyncTaskWrapper
{
private Func<Task> _action;
public SyncTaskWrapper(Action action)
=> _action = CreateFunc(action);
private static Func<Task> CreateFunc(Action action)
=> () =>
{
try
{
action();
return Task.CompletedTask;
}
catch (Exception exception)
{
return Task.FromException(exception);
}
};
public static implicit operator Func<Task>(SyncTaskWrapper #this)
=> #this._action;
}
with usage
_pipe.Enqueue(new SyncTaskWrapper(() =>
_output = outputBuilder(_results)));

How to convert below code used for the database connection using EF 6 to async task in C#?

I am trying to create the async task for the already existing code in my project for the database connection using EF 6.
I have created async task and it works fine, you can refer Using Async Task section for the code. But I want to rewrite The existing code of the project section as async task to maintain the consistency in the project.
Using Async Task: The below code works fine.
public static async Task<Student> InsertAsync(Student student)
{
try
{
using(PracticeContext context = new PracticeContext())
{
Repository<Student> repository = new Repository<Student>(context);
return await repository.InsertAsync(student);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
The existing code of the project:
I want to implement the below code as async task for both the Insert() and Execute() methods. So, that the data will be added to the database without holding the UI for the long time and make the project more user friendly.
Please suggest or provide the async implementation of the below codes.
public static Student Insert(Student student)
{
try
{
return Execute<Student, Student>((repository) => {
return repository.Insert(student);
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
private static TResult Execute<TResult, T>(Func<Repository<T>, TResult> func) where T: class
{
using(PracticeContext context = new PracticeContext())
{
try
{
return func(new Repository<T>(context));
}
catch(Exception ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
I would be glad to add more stuffs if required to make the questions more accurate and understandable.
The first thing you do is change the lowest-level call to use the asynchronous version and use async in its enclosing method/lambda. Then let the async grow from there. So the first step would be:
return Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
This code then requires Execute to allow asynchronous delegates. At this step, we probably want other code to continue using the synchronous Execute, so we can copy/paste it and make the new overload take an asynchronous delegate:
private static async Task<TResult> Execute<TResult, T>(Func<Repository<T>, Task<TResult>> func) where T: class
{
using(PracticeContext context = new PracticeContext())
{
try
{
return await func(new Repository<T>(context));
}
catch(Exception ex)
{
Console.WriteLine(ex);
throw new Exception("Error Occured.");
}
}
}
Now that the asynchronous Execute returns a Task<T>, we then need to await it back in the calling method:
return await Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
which then makes the calling method asynchronous as well:
public static async Task<Student> InsertAsync(Student student)
{
try
{
return await Execute<Student, Student>(async (repository) => {
return await repository.Insert(student);
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}

How do I return the TaskStatus when making a synchronous call asynchronous?

I have a old data access library that I need to use in my ASP.NET MVC application but I'm having trouble bringing it into the MVC world where many server-side operations are expected to be asynchronous. My data access library looks a like this:
public class MyOldDAL
{
public TaskResult CreateUser(string userName)
{
try
{
// Do user creation
return new TaskResult { Success = true, Message = "success" };
}
catch (Exception ex)
{
return new TaskResult { Success = false, Message = ex.Message };
}
}
}
And is called by my MVC application like this:
public class MyUserStore : IUserStore<ApplicationUser>
{
private readonly MyOldDAL _dal = new MyOldDAL();
public async Task CreateAsync(ApplicationUser user)
{
await Task.Run(() => _dal.CreateUser(user.UserName));
}
}
This is fine until the method in Task.Run() fails for some reason. I'd like to be able to return TaskStatus.Faulted if TaskResult.Success is false but I can't find an example online on how to do it properly - all my Google searches turn up is how to use Task<T> which the IUserStore interface doesn't permit.
For the record, much as I'd like to I can't change MyOldDAL - it's targeting .NET 3.5 so no async or await there!
The normal way to report errors from tasks is via exceptions, so you'll just need to do that transformation yourself:
public class MyUserStore : IUserStore<ApplicationUser>
{
private readonly MyOldDAL _dal = new MyOldDAL();
public Task CreateAsync(ApplicationUser user)
{
var result = _dal.CreateUser(user.UserName);
if (result.Success)
return Task.CompletedTask;
return Task.FromException(new InvalidOperationException(result.Message));
}
}
Note that Task.Run should not be used on ASP.NET.
Note: As Stephen Cleary noticed in his answer, Task.Run should not be used on ASP.NET.
Original answer (before comments):
Your CreateAsync method should normally be like this:
public async Task<TaskResult> CreateAsync(ApplicationUser user)
{
return await Task.Run(() => _dal.CreateUser(user.UserName));
}
But if you can't return Task<TaskResult> from CreateAsync method... well, than you can't obtain TaskResult from CreateAsync by definition. In that case you can store result locally:
private TaskResult taskResult;
public async Task CreateAsync(ApplicationUser user)
{
var result = await Task.Run(() => _dal.CreateUser(user.UserName));
this.taskResult = result;
// process taskResult wherether you need
}
Or raise event with TaskResult payload, allowing client of MyUserStore to subscribe to this event:
public event EventHandler<TaskResult> TaskCompleted;
public async Task CreateAsync(ApplicationUser user)
{
var result = await Task.Run(() => _dal.CreateUser(user.UserName));
this.OnTaskCompleted(result);
}
private void OnTaskCompleted(TaskResult result)
{
this.TaskCompleted?.Invoke(this, result);
}

await a Task and silently stop on cancel or failure

What I would like to write is the following:
async void Foo()
{
var result = await GetMyTask().IgnoreCancelAndFailure();
ProcessResult(result);
}
Instead of:
void Foo()
{
GetMyTask().ContinueWith(task => ProcessResult(task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
}
However I don't know how to implement the method IgnoreCancelAndFailure, which would have the following signature:
//On cancel or failure this task should simply stop and never complete.
Task<T> IgnoreCancelAndFailure<T>(this Task<T> task)
{
throw new NotImplementedException();
}
If possible, how should I implement IgnoreCancelAndFailure?
You could do something like that, but you need to know what you want the method to return in case of failure, since a return value is expected:
public static async Task<T> IgnoreCancelAndFailure<T>(this Task<T> task)
{
try
{
return await task;
}
catch
{
return ???; // whatever you want to return in this case
}
}
If it's a Task with no result, just leave the catch empty (or perhaps log the exception... swallowed exceptions make for hard debugging)
If you just want to execute ProcessResult only when GetMyTask succeeds, you can do this:
async void Foo()
{
try
{
var result = await GetMyTask();
ProcessResult(result);
}
catch(Exception ex)
{
// handle the exception somehow, or ignore it (not recommended)
}
}
You will never be able to stop your code from continuing expect when killing the thread or process. keep in mind that the await task can be considered a function call that will always have to return a value or throw an exception.
The closest way to shorten your code is creating a wrapper function that uses the ProcessResult method as Action argument.
Something like that:
public static async Task IgnoreCancelAndFailure<T>(this Task<T> task, Action<T> resultProcessor)
{
task.ContinueWith(t => resultProcessor(t.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
}
async void Foo()
{
GetMyTask().IgnoreCancelAndFailure(ProcessResult);
}
I think I found the answer. The following seems to do the trick. It uses the awaitable pattern. Could you guys confirm that this isn't evil?
class User
{
async void Foo()
{
var result = await GetMyTask().IgnoreCancelAndFailure();
ProcessResult(result);
}
}
public static class TaskExtenstions
{
public static SilentTask<T> IgnoreCancelAndFailure<T>(this Task<T> task)
{
return new SilentTask<T>(task);
}
}
public class SilentTask<T>
{
private readonly Task<T> _inner;
public SilentTask(Task<T> inner)
{
_inner = inner;
}
public SilentAwaiter GetAwaiter()
{
return new SilentAwaiter(_inner);
}
public class SilentAwaiter : INotifyCompletion
{
private readonly TaskAwaiter<T> _inner;
private readonly Task<T> _task;
public SilentAwaiter(Task<T> task)
{
_task = task;
_inner = task.GetAwaiter();
}
public bool IsCompleted
{
get
{
return _task.Status == TaskStatus.RanToCompletion;
}
}
public void OnCompleted(Action continuation)
{
_inner.OnCompleted(() =>
{
if (IsCompleted)
{
continuation();
}
});
}
public T GetResult()
{
return _inner.GetResult();
}
}
}

Categories