【问题标题】:Asp.net mvc async controller method testsAsp.net mvc 异步控制器方法测试
【发布时间】:2015-02-06 01:08:36
【问题描述】:

我一直在尝试学习单元测试,而不是 TDD,我尝试在控制器中对方法进行单元测试。我有 Unity 3.5、Asp.Net MVC 5.1、Entity Framework 6.1.2、MS 测试、NSubstitute 1.8.1.0 和 Visual Studio 2013 Update 3。我有一个包含 3 个项目的解决方案,一个是普通的 MVC 5 项目,一个是单元测试项目和一个类库都被正确引用并且工作正常。我的代码编译正常,一切都很好。我现在正在尝试测试我的异步索引操作,这就是我的问题。我遵循了有关 EF6 测试的 msdn 文档,因此我有一个从上下文创建的接口,并在我的控制器中使用它,如下所示:

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 的任务,所以我要反对什么?我了解到您针对模拟断言并使用存根来满足依赖关系。那我该怎么办?我读过的单元测试是要走的路,我不想放弃,所以我该怎么办?请帮忙?!

【问题讨论】:

  • 如果你不明白你应该做什么,那么 SO 是一个错误的地方来帮助你 - 你应该把你的问题变成更具体的东西,比如“我想检查 XXXX 和 YYYY”.. .
  • 您能否澄清一下“结果是 ActionResult 的任务”在您的代码示例中的位置?

标签: c# asp.net-mvc entity-framework


【解决方案1】:

从我所看到的情况来看,我认为您的事情可能过于复杂。我认为测试的想法是将所有内容分解为最简单的形式(单位)。因此,出于测试目的,我可能会以编程方式创建帐户、银行等实例。这样做的原因是为了测试您的逻辑是否按照它所说的那样做,而没有更改数据,如果您使用数据库,可能会发生这种情况。

通过 EF 测试,我会检查是否从每个结果集中返回了任何项目。

我还将测试您想要执行的基本 EF 操作,即它是否返回所有银行?它是否返回所有帐户?你可以创建一个银行吗?你可以创建一个帐户等等。

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

本质上,您是在检查它是否通过,您需要定义使测试通过或失败的原因。

这可能很简单:

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

与此集成的 Selenium 在测试表单时也非常有用。

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2012-02-24
    相关资源
    最近更新 更多