简体   繁体   中英

Asp.net mvc async controller method tests

I have been trying to learn unit testing, not quite TDD where I am trying to unit test methods in my controllers. I have Unity 3.5, Asp.Net MVC 5.1, Entity Framework 6.1.2, MS Tests, NSubstitute 1.8.1.0 and Visual Studio 2013 Update 3. I have a solution with 3 projects, One a normal MVC 5 project, a Unit Test project and a class Library all referenced properly and working fine. My code compiles alright and everything is well. I am now trying to Test my async index action and therein lies my issues. I followed the msdn documentation on EF6 testing so I have an Interface that I created from my Context and used that in my controller like so:

public interface ITestContext : IDisposable
{
    IDbSet<Account> Accounts { get; set; }
    IDbSet<Bank> Banks { get; set; }
    DbEntityEntry Entry(object o);
    int SaveChanges();
    Task<int> SaveChangesAsync();
}

Then my context class is like so:

public class TestContext : DbContext, ITestContext
{
    public TestContext(): base("DefaultConnection"){}

    public virtual IDbSet<Account> Accounts { get; set; }
    public virtual IDbSet<Bank> Banks { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);
    }
    public override int SaveChanges()
    {
        return base.SaveChanges();
    }

    public override Task<int> SaveChangesAsync()
    {
        return base.SaveChangesAsync();
    }

    public DbEntityEntry Entity(object o)
    {
        return base.Entry(o);
    }
}

so I use the Interface in my controller using DI. All my controller methods are async methods so my index action looks like so:

public class AccountsController : Controller
{
    private ITestContext db;

    public AccountsController(ITestContext _db)
    {
        db = _db;
        //db1 = bnk;
    }

    // GET: Accounts
    public async Task<ActionResult> Index()
    {
        var accounts = db.Accounts.Include(a => a.Bank);
        return View(await accounts.ToListAsync());
    }

I created a TestDbAsyncEnumerator and TestDbAsyncQueryProvider taking tips from NSubstitute DbSet / IQueryable<T> . So the annoying thing is what to do in order to test this index method? This is how far I have come:

[TestMethod]
    public async Task TestingIndexControllerAction()
    {
        var testdb = new List<Account>
        {
            new Account{ Bank=new Bank{Name="Zenith"}, AccountBalance=19000, AccountName="John Doe"}
        }.AsQueryable();
        var test = Substitute.For<IDbSet<Account>, IDbAsyncEnumerable<Account>>().Initailize(testdb);
        var context = Substitute.For<ITestContext>();
        context.Accounts.Returns(test);
        var controller = new AccountsController(context);
        var result = await controller.Index();
    }

Can someone please help me figure this out and point me in the right direction? I have read blogs and a book but still can't understand what I should be doing here? result is a Task of ActionResult so what am I asserting against? I have learned that you assert against a mock and use stubs to satisfy dependencies. so then what do I do? Unit testing I have read is the way to go and I don't want to give up so what do I do here? Please help?!

I think your probably overcomplicating things from what I can see. The idea of tests as I see it is to break everything down to its simplest form(units). So I would probably create instances of Account, Bank etc programatically for testing purposes. The reason for this is to test that your logic is doing what it says it is without the the changing of data, which can happen if you working of database.

With the EF testing, I would check to see if any items are returned from each result set.

Also I would test basic EF operations that you want to perform, ie does it return all banks?, does it return all accounts?, can you create a bank?, can you create an account and so on.

I use NUnit, but most unit testing frameworks are similar.

In essence you are checking to see if its passed or not and you need to define what makes the test pass or fail.

This could be something as simple as this:

Assert.IsTrue(result.Equals("Hello World"));

Also Selenium integrated with this can be very useful when testing forms.

Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM