2015-02-06 103 views
0

我一直在努力学习单元测试,不太TDD在那里我试图单元测试方法在我的控制器。我有Unity 3.5,Asp.Net MVC 5.1,实体框架6.1.2,MS测试,NSubstitute 1.8.1.0和Visual Studio 2013更新3.我有3个项目的解决方案,一个是正常的MVC 5项目,一个单元测试项目和一个类库所有引用正常,工作正常。我的代码编译好,一切都很好。我现在试图测试我的异步索引行为,其中存在我的问题。我也跟着上EF6测试MSDN文档,所以我有我从我的上下文中创建和使用,在我的控制,像这样的接口:Asp.net MVC异步控制器的方法测试

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

然后我的上下文类是像这样:

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); 
    } 
} 

所以我在使用DI的控制器中使用接口。我所有的控制方法是异步方法,使我的索引动作看起来像这样:

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()); 
    } 

我创建了一个TestDbAsyncEnumerator和TestDbAsyncQueryProvider采取提示从NSubstitute DbSet/IQueryable<T>。所以烦人的事情是为了测试这个索引方法该怎么做?这是我走了多远:

[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(); 
    } 

有人能帮我解决这个问题,并指出我在正确的方向吗?我已经阅读过博客和一本书,但仍然无法理解我应该在这里做什么?结果是一个ActionResult的任务,所以我主张什么?我已经了解到,你坚持反对模拟并使用存根来满足依赖关系。那么我该怎么办?我读过的单元测试是要走的路,我不想放弃,所以我在这里做什么?请帮忙?!

+0

如果你不明白你应该做什么,那么SO是错误的地方来帮助你 - 你应该把你的问题变成更具体的东西,比如“我想检查XXXX和YYYY”...... – 2015-02-06 01:15:28

+0

你能否请澄清你的代码示例中“结果是ActionResult的任务”的位置? – 2015-02-06 01:15:56

回答

1

我觉得你从我所看到的可能是过于复杂的事情。我所看到的测试理念是将所有东西都打破成最简单的形式(单位)。所以我可能会为了测试目的而编程创建Account,Bank等实例。原因是为了测试你的逻辑是否正在做它所说的没有数据变化的情况,如果你使用数据库的话会发生这种情况。

随着EF的测试,我会检查,看看是否有任何物品从每个结果集返回。

另外我想测试要执行基本EF操作,即它返回所有银行?它返回所有帐户?您可以创建一个银行?您可以创建一个帐户等等。

我使用NUnit,但大多数的单元测试框架是相似的。

从本质上说要检查,看看它的通过与否,你需要定义什么样的测试合格或不合格。

这可能是这么简单的东西:

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

而且硒这种集成测试表单时是非常有用的。

希望有所帮助。