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

Kal*_*exx 10 c# unit-testing functional-testing sql-server-ce entity-framework-4

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

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

我的第一个想法是TransactionScopeTestInitialize方法中初始化a ,并将事务处理掉TestCleanup.不幸的是,Sql CE4不支持事务.

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

我试图改变TestInitializeTestCleanup标签ClassInitialize,并ClassCleanup为我的测试类,但有差错NullReferenceException,由于运行前的测试ClassInitialize(或使其出现. 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!
        }
    }
Run Code Online (Sandbox Code Playgroud)

Bui*_*ted 4

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

System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
    new System.Data.Entity.Database.DropCreateDatabaseAlways<YourEntityFrameworkClass>());
Run Code Online (Sandbox Code Playgroud)

这将导致实体框架在运行测试时始终重新创建数据库。

顺便说一句,您可以创建一个继承自 的替代类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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在初始化中将调用更改为:

System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
    new DataContextInitializer());
Run Code Online (Sandbox Code Playgroud)