Christopher Francisco
Christopher Francisco

Reputation: 16268

Returning a Task<TEntity> correctly in ASP

I have a GenericRepository and a GenericMockRepository. I'm working with async methods.

Here's my code

// GenericRepository - uses a DbContext context subclass with connection strings and stuff
public Task<TEntity> GetByIDAsync(object id) {
    return context.FindAsync(id)
}

// GenericMockRepository - uses a List<TEntity> entities
public Task<TEntity> GetByIDAsync(object id) {

    // THIS DOESN'T WORK

    return new Task<TEntity>(() => {
        return entities.SingleOrDefault(entity => {
            var property = entity.GetType().GetProperty("ID");
            if (property != null && property.GetValue(entity) == id) {
                return true;
            }
            return false;
        });
    });
}

Basically, the first one is called when the request goes through a browser and the Controller is instantiated by the framework. The second one gets called from Unit Test project

For both cases, Controller's Details() method goes like this:

// inside Details()
Customer customer = await UnitOfWork.CustomerRepository.GetByIDAsync(id.GetValueOrDefault());

And here is the test case:

[TestMethod]
    public async void CanRetrieveSingleContact() {
        //Arrange
        SetUp();
        Customer customer = Customers.FirstOrDefault();

        // Act
        ViewResult result = await Controller.Details(customer.ID) as ViewResult;

        // Assert
        Customer model = result.ViewData.Model as Customer;
        Assert.AreEqual(customer, model);
    }

There is no documentation how to async test, so up to this point:

  1. if I declare this test method as void, it doesn't get tested
  2. as Task or Task or Task it runs but never ends nor gives results

Upvotes: 0

Views: 113

Answers (1)

beautifulcoder
beautifulcoder

Reputation: 11320

Change

public async void CanRetrieveSingleContact()

To

public async Task CanRetrieveSingleContact()

TAP programming and unit testing is a bit tricky, and yes, it fails without telling you why.

Test explorer needs to know what it's working on. If you return void, it ignores it and goes on its merry way. But if you return Task, it knows to wait.

One other thing you are missing is:

 public async Task<TEntity> GetByIDAsync(object id)

Then

return await Task.FromResult<TEntity>(entities.SingleOrDefault( ... ));

It needs to wait on your asynchronous method.

Upvotes: 1

Related Questions