c# - 如何使用 Sql CE 4 数据库进行功能测试

标签 c# unit-testing entity-framework-4 functional-testing sql-server-ce

由于 Linq-to-Entities (EF4) 和 Linq-to-Objects 之间的潜在差异,我需要使用实际的数据库来确保我的查询类正确地从 EF 检索数据。 Sql CE 4 似乎是完美的工具,但是我遇到了一些小问题。这些测试使用的是 MsTest。

我遇到的问题是,如果数据库没有被重新创建(由于模型更改),数据会在每次测试后不断添加到数据库中,而不会删除数据。这可能会导致测试冲突,查询返回的数据多于预期。

我的第一个想法是在 TestInitialize 方法中初始化一个 TransactionScope,并在 TestCleanup 中处理事务。不幸的是,Sql CE4 不支持事务。

我的下一个想法是通过 File.Delete() 调用删除 TestCleanup 中的数据库。不幸的是,这似乎在第一个测试运行后不起作用,因为第一个测试的 TestCleanup 似乎删除了数据库,但是第一个测试之后的每个测试似乎都没有重新创建数据库,因此它给出了找不到数据库文件的错误。

我试图将测试类的 TestInitializeTestCleanup 标记更改为 ClassInitializeClassCleanup,但是由于在 ClassInitialize 之前运行的测试,出现了 NullReferenceException 错误(或者看起来是这样。ClassInitialize 在基类中,所以这可能是它的原因).

我已经用尽了有效使用 Sql CE4 进行测试的方法。有没有人有更好的想法?


编辑: 我最终想出了一个解决方案。在我的 EF 单元测试基类中,我启动了我的数据上下文的一个新实例,然后调用 context.Database.Delete()context.Database.Create()。单元测试运行速度稍慢,但现在我可以使用真实数据库进行有效的单元测试


最终编辑: 在与 Microsoft 来回发送一些电子邮件后,发现 TransactionScope 现在允许在 SqlCE 中使用最新版本的 SqlCE。但是,如果您使用的是 EF4,则存在一些限制,因为您必须在开始事务之前显式打开数据库连接。以下代码展示了如何成功使用 Sql CE 进行单元/功能测试的示例:

    [TestMethod]
    public void My_SqlCeScenario ()
    {
        using (var context = new MySQLCeModelContext()) //ß derived from DbContext
        {
            ObjectContext objctx = ((IObjectContextAdapter)context).ObjectContext;
            objctx.Connection.Open(); //ß Open your connection explicitly
            using (TransactionScope tx = new TransactionScope())
            {

                var product = new Product() { Name = "Vegemite" };
                context.Products.Add(product);
                context.SaveChanges();
            }
            objctx.Connection.Close(); //ß close it when done!
        }
    }

最佳答案

在您的 TestInitialize 中,您应该执行以下操作:

System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
    new System.Data.Entity.Database.DropCreateDatabaseAlways<YourEntityFrameworkClass>());

这将导致 Entity Framework 在测试运行时始终重新创建数据库。

顺便说一句,您可以创建一个继承自 DropCreateDatabaseAlways 的替代类。这将允许您每次都使用设置的数据为您的数据库做种。

public class DataContextInitializer : DropCreateDatabaseAlways<YourEntityFrameworkClass> {
    protected override void Seed(DataContext context) {
        context.Users.Add(new User() { Name = "Test User 1", Email = "test@test.com" });
        context.SaveChanges();
    }
}

然后在您的 Initialize 中将调用更改为:

System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
    new DataContextInitializer());

关于c# - 如何使用 Sql CE 4 数据库进行功能测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4676460/

相关文章:

ios - 如何使用 OCMockito stub 类方法?

stored-procedures - 存储过程未出现在 EF 代码中

entity-framework-4 - 工作单元应该指向服务层还是存储库?

c# - .NET 单元测试 - 如何区分变量初始化的 TestMethods

c# - 如何从 web api Controller 返回文件?

c# - [WCF]同一个进程中的两个服务

c# - Linq 对象引用未设置为对象的实例 - 内部集合为空

.net - 用于生成边界条件的单元测试工具

.net - EF 4.0 支持哪些功能?

c# - 为什么.NET 没有双向枚举器?