单元测试异步数据库方法

时间:2015-03-08 20:23:19

标签: c# entity-framework unit-testing async-await mstest

我有一个Web API,我想使用MS Test进行测试。我想特别测试一个控制器。这是初始化代码:

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]重置器),但底层数据库仍然是相同的,并且在插入新的模拟对象时我遇到了许多关键冲突。另一个想法是在内存中设置一个新数据库并具有完全独立的实例。我找到了Effort,但我认为这是一种矫枉过正的行为,我接近它是错误的。

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

1 个答案:

答案 0 :(得分:1)

我想你可能会以错误的方式看待这个问题。

单元测试的目的是测试与任何其他单元隔离的功能单元。没有必要单元测试实体框架,它已经过彻底测试。无论何时创建CRUD操作的测试,您实际上都在创建集成测试,而不是单元测试。

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

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