2015-03-08 84 views
0

我有一个Web API,我想使用MS Test进行测试。我想特别测试一个控制器。这是init代码:单元测试异步数据库方法

public class MyControllerTests 
{ 
    private static MyController controller; 

    [AssemblyInitialize] 
    public static void Initialize(TestContext context) 
    { 
     controller = new MyController(); 

     IoC.Register(Component.For<IDbContextFactory>().ImplementedBy<MockDbContextFactory>()); 
     // other config 
    } 
    // test methods, all async 
} 

这是模拟上下文工厂。是否在所有API方法中使用它来获取数据库上下文。

public class MockDbContextFactory : IDbContextFactory 
{ 
    MyContext context; 

    public MyBaseContext GetContext() 
    { 
     if (context == null) 
     { 
      context = new MyContext(new DropCreateDatabaseAlways<MyContext>()); 

      //populate with mock data... 
     } 

     return context; 
    } 
} 

一切都很好,直到我添加了删除方法的测试。它在其他方法之前完成,因此它从共享上下文中删除对象,而其他测试失败。不,我有两个想法:每个方法的新上下文(使用[TestInitialize] resetter),但底层数据库仍然是相同的,插入新的模拟对象时,我会遇到很多关键冲突。另一个想法是在内存中设置一个新的数据库并拥有完全独立的实例。我发现Effort,但我相信这是一个矫枉过正的事情,我正在接近错误。

我正在使用Castle Windsor作为IoC容器,以防在IoC级别上执行此操作。

+0

巧合的是,我最近写了一篇关于使用Effort单元测试你的'DbContext'的博文。如果你决定走这条路线(实际上,它很容易设置),你可能会觉得很有趣:http://vannevel.net/blog/2015/02/26/11/ – 2015-03-08 20:26:14

+0

附注:你的东西没有发布需要/谈论异步等待......看起来你正在谈论缺乏隐式测试排序(这是件好事) - 你会从同步调用中获得同样的失败......这可能是个好主意编辑出“异步”出了问题。 – 2015-03-08 21:03:45

回答

1

我想你可能是看着这个错误的方式。

单元测试的目的是测试与任何其他单元隔离的功能单元。没有必要单元测试实体框架,它已经过彻底的测试。任何时候你创建一个CRUD操作的测试,你真的创建一个集成测试,而不是单元测试。

如果您确实需要测试您的CRUD操作,那么您的模拟工厂应该只是返回所有传递给它的操作的成功,或者将数据保存到本地传回以进行验证。它不应该创建一个“测试”DbContext对象,该对象不仅要与数据库交互,还要与其他测试交互。你的单元测试应该专注于验证被测函数的操作。

现在,如果您的意图是执行集成测试,那么通常的做法是让测试本身插入要删除的对象。试图删除由另一个测试插入的记录的删除测试总是会对时间带来挑战。另外,没有理由甚至担心删除由插入测试插入的对象,使用DropCreateDatabaseAlways

+0

在删除测试中创建要删除的对象似乎非常明显,我不相信我没有想出。 – 2015-03-08 21:14:44