Using Microsoft Fakes to Mock - c#

I have sealed classes with async(.net 4.5) methods that need to be mocked. I'm using Microsoft Fakes and so they will be "shims". The following code is an example of what I need to do. It builds but when run and the "LoginAsync" method within the "Login" controller method is called, the test hangs.
[TestMethod]
public async Task LoginPost_Returns() {
using (ShimsContext.Create()) {
var c = new TestController();
var user=new User();
Fakes.ShimUserManager.AllInstances.LoginAsyncString = (um, u) => new Task<IUser>(() => { return user; });
//call controller method
var result = await c.Login(model, returnUrl) as ViewResult;
var expectedViewName = "Index";
Assert.IsNotNull(result);
Assert.AreEqual(expectedViewName, result.ViewName);
}
//Controller method
public async Task<ActionResult> Login(LoginModel model, string returnUrl) {
var user = await UserManager.LoginAsync(model.UserName, model.password);
return View();
}

Don't use the Task constructor in async code. If you just need a completed Task with a return value, use Task.FromResult:
IUser user = new User();
Fakes.ShimUserManager.AllInstances.LoginAsyncString = (um, u) => Task.FromResult(user);
As an additional tip, it's a good idea to cover these cases in your unit tests:
Synchronous success (Task.FromResult(user)).
Asynchronous success (Task.Run(() => user)).
Asynchronous error (Task.Run(() => { throw new InvalidOperationException("or whatever"); return user; })).

Fakes.ShimUserManager.AllInstances.LoginAsyncString =
(um, u) => new Task<IUser>(() => { return user; });
This creates an unstarted Task. Your code hangs, because the Task is never started. To fix that, you can:
Use Task.Run() (or Task.Factory.StartNew()), which returns an already started Task.
Use Task.FromResult(). which returns an already completed Task.
Make the lambda async:
Fakes.ShimUserManager.AllInstances.LoginAsyncString = async (um, u) => user;

Related

Casting an ActionResult rather than IActionResult to an OKObjectResult for testing a 200 status code?

I am moving to use and ActionResult rather than IActionResult so that Swagger automatically picks up my types, but I am getting an error saying that I cannot cast an ActionResult to an OkObjectResult.
How do I cast to an OKObjectResult for testing a 200 status code?
My IActionResult Controller
[HttpGet]
public async Task<IActionResult<IEnumerable<Listing>>> Get()
{
var listings = await listingService.GetAllListings();
if (listings.Any())
{
return Ok(listings);
}
return NotFound();
}
My ActionResult Controller
[HttpGet]
public async Task<ActionResult<IEnumerable<Listing>>> Get()
{
var listings = await listingService.GetAllListings();
if (listings.Any())
{
return Ok(listings);
}
return NotFound();
}
My Test
[Fact]
public async Task ShouldReturnA200StatusCode()
{
var res = (OkObjectResult)await sut.Get();
res.StatusCode.Should().Be(200);
}
Take a look about my solution about how to validate HTTP status code in unit test using XUnit.
[Fact]
public async Task UpdateProduct_When_Product_IsValid_ShouldReturn200()
{
//Arrange
ProductDto productDto = new DataGenerator()
.GenerateProductDto_Valid(1)
.First();
var result = _productAppServiceMock.Setup(p => p
.UpdateAsync(
It.IsAny<Guid>(),
It.IsAny<ProductDto>()))
.ReturnsAsync(() => productDto);
//Act
var itemHttp = await productController
.UpdateProductAsync(productDto.Id, productDto);
//Assert
_productAppServiceMock.Verify(p => p.UpdateAsync(It.IsAny<Guid>(),
productDto), times: Times.Once);
Assert.Equal(typeof(Microsoft.AspNetCore.Mvc.OkObjectResult), itemHttp.GetType());
}
Following the guidance of this answer to a similar question you need to cast the Result of the .Get() method (rather than just the .Get() method) and then you can check that for the 200 OK StatusCode
[Fact]
public async Task ShouldReturnA200StatusCode()
{
var res = await sut.Get();
var okObj = res.Result as ObjectResult;
okObj.StatusCode.Should().Be(StatusCodes.Status200OK);
}
Following on from the comments above I have used the ObjectResult type with the aim to not coerce the 200 status code and have used the as casting.

Nothing happens when accessing an async task from repository in asp.net?

I am creating an async task in a repo, and then accessing it from the controller to try and minimize the logic in the controller.
The thing is, that when I used the exact same logic in the controller, there was an output, now that I'm accessing this way, it isn't searching for it.
Repository:
public async Task<List<Guests>> GetGuesteByAsync(string Search)
{
var list = GetAll();
var listquery = from x in context.Guest select x;
if (!string.IsNullOrEmpty(Search))
{
listquery = listquery.Where(x => x.FullName.Contains(Search) || x.Organisation.Contains(Search));
}
return await context.Guests.ToListAsync();
}
The controller:
[HttpGet]
public async Task<ActionResult> Index(string Search)
{
ViewData["Getsearchinput"] = EmpSearch;
//List<Guests> listofguests = await repository.GetGuesteByAsync(Search);
var res = await (repository.GetGuesteByAsync(Search));
return View(res);
}
This returns all entries.
return await context.Guests.ToListAsync();
I think you should use your query. Can you try this?
return await listquery.ToListAsync();

ASP.NET Core: Making service asynchronous

I have an ASP.NET core application where I use a service layer between my controllers and Entity Framework.
Currently my services are synchronous, but I would like to make them asynchronous.
This is an controller example:
public async Task<IActionResult> Search(BusinessesSearchModel model)
{
var resultModel = await _businessService.Search(model);
return Ok(resultModel);
}
And this is an example of my service:
public interface IBusinessesService
{
Task<BusinessResultListModel> Search(BusinessesSearchModel model);
}
public class BusinessesService : IBusinessesService
{
public async Task<BusinessResultListModel> Search(BusinessesSearchModel model)
{
var queryResult = (from b in MyDBContext.Businesses
where b.Name.Contains(model.Name)
&& b.Phone.Contains(model.Phone)
select new BusinessesListModel
{
ID = b.ID,
Name = b.Name,
Phone = b.Phone
}
).ToList();
var resultModel = new BusinessResultListModel();
resultModel.data = queryResult;
resultModel.othervalue = "other value";
return resultModel;
}
}
This does not work. Visual Studio tells me:
This async method lacks 'await' operators and will run synchronously
Where should I add await to make this async?
Your code isn't doing anyting asynchronously. To utilize the await/async API, you need to be invoking an async method inside your own method (unless you want to implement the async logic yourself).
In your case, if you're using Entity Framework, you can use it's async methods for querying:
public class BusinessesService : IBusinessesService
{
public async Task<BusinessResultListModel> Search(BusinessesSearchModel model)
{
var queryResult = await _context.YourEntity.Where(x => x.SomeProperty == model.Query).ToListAsync(); //<--- This is your async call, awaiting the ToListAsync() method
var resultModel = new BusinessResultListModel();
resultModel.data = queryResult;
resultModel.othervalue = "other value";
return resultModel;
}
}
Other async methods in EntityFramework are FirstOrDefaultAsync(), SingleOrDefaultAsync(), SaveChangesAsync() and so on
you are missing the async within linq.
for example:
public async Task<IEnumerable<SchedulerJob>> GetAllByIdsAsync(IEnumerable<int> ids, CancellationToken cancellationToken = default(CancellationToken))
{
return await Context.SchedulerJobs
.Include(s => s.Program)
.Where(job => ids.Contains(job.Id))
.ToListAsync(cancellationToken);
}
the ToListAsync(cancellationToken); in combination with await, and you are set to go!
i see you edited the page:
you need to do:
public async Task<BusinessResultListModel> Search(BusinessesSearchModel model)
{
//something like:
var queryResult = await (from b in MyDBContext.Businesses
where b.Name.Contains(model.Name)
&& b.Phone.Contains(model.Phone)
select new BusinessesListModel
{
ID = b.ID,
Name = b.Name,
Phone = b.Phone
}
).ToListAsync();
var resultModel = new BusinessResultListModel();
resultModel.data = queryResult;
resultModel.othervalue = "other value";
return resultModel;
}

Create Async Wrapper for a NonAsync Method

I am writting a middleware for Asp.Net Identity UserStore where the caller expects a Task and the Method to be called is NonAsynch.
Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = Utility.SetSecurityStamp(user, stamp); // needs to be called as Async
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
return ??? ; // How do i get a task to return here ?
}
How do i return a Task out of res and stamp? Tried Task.FromResult but it says only one type argument is allowed.
Use the async/await pattern.
Wrap the call of the Utility.SetSecurityStamp method into a Task using Task.Run
So your code could become something like that:
async Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = await Task.Run(() => Utility.SetSecurityStamp(user, stamp));
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
}
Or you can just use Task.FromResult to make your method awaitable :
async Task IUserSecurityStampStore<T, string>.SetSecurityStampAsync(T user, string stamp)
{
var res = Utility.SetSecurityStamp(user, stamp);
var identityUser = ToIdentityUser(res);
SetApplicationUser(user, identityUser);
await Task.FromResult(0);
}

Any reason to use async/await when the controller action is sync?

Lets say I have a controller action that cannot be made async (for various reasons), but I have a service that (through several methods) calls a rest service using HttpClient. Is there any thing to gain by using the async client and using .Wait or .Result? Or would it be less performant to use the synchronous method?
So either:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.Get(id);
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public ProcessedResponse Get(int id)
{
var client = new HttpClient();
var result = client.Get(_url+id);
return Process(result);
}
Or:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.GetAsync(id).Result;
//or, .Wait, or Task.Run(...), or something similar
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var result = await client.GetAsync(_url+id);
return await Process(result);
}
Is there any thing to gain by using the async client and wrapping the
method in Task.Run(() => _myService.Get()).Result?
The only thing you'll most likely end up gaining is a deadlock. Think about it, you're queuing a naturally asynchronous method on a thread-pool thread, where the ASP.NET already gave you a thread to process you Action inside. There isn't much sense in that.
If you want to go async, and think you'll actually benefit from the scale provided by asynchrony, then you should re-factor your controllers to be async as well and return a Task<T>, where you can await those asynchronous methods.
So I'd either stay synchronous, or re-factor the code top to bottom to support async:
//MyController.cs
public async Task<ActionResult> GetSomethingAsync(int id)
{
//lots of stuff here
await GetAsync(id);
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var result = await client.GetAsync(_url+id);
return await Process(result);
}
In your scenario, no there isn't a good reason, but lets add some functionality:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.GetAsync(id).Result;
//or, .Wait, or Task.Run(...), or something similar
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var pendingResult1 = client.GetAsync(_url+id);
var pendingResult2 = someAsyncOperation();
var result3 = someSyncOperation();
var result1 = await pendingResult;
var result2 = await pendingResult2;
return await Process(result1, result2, result3);
}
Now, since your request takes a while to complete, someAsynchOperation starts executing immediately instead of waiting for GetAsync() to complete. someSyncOperation is also being executed in the meantime.
Without the async keyword, you would not be able to use await, so it's better to have it if you plan to have asynchronous execution inside your funciton.
It gets interesting when do can do it like this
//MyController.cs
public ActionResult GetSomething(int id)
{
var processedResponseTask = _myService.GetAsyn(id)
//lots of stuff here (1)
var processedResponseTask.Wait();
var processedResponse = processedResponseTask.Result;
//lots more stuff here (2)
return new ContentResult(result);
}
now the lots of stuff here(1) is done in parallel with your async task. (Or if you called your service twice for example). If you don't actually do a lot around lots of stuff here(1) then there isn't much of a point.

Categories

Resources