实体框架代码首先:如何种子数据库进行单元测试 [英] Entity Framework Code First: How to seed a database for unit testing

查看:119
本文介绍了实体框架代码首先:如何种子数据库进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题和代码是基于代码优先实体框架单元测试示例博客文章。我正在使用SQL Compact 4.0,因此我的单元测试使用与博客文章中描述的真实数据相对的实际数据库运行。

My question and code is based on the Code First Entity Framework Unit Test Examples blog post. I am using SQL Compact 4.0 and as such my unit tests are running against the actual database using real data similar to what is being described in the blog post.

我想在某些表格中使用默认值种子我的生产数据库,但是当运行我的单元测试时,我想添加额外的数据并更新一些默认值。

I want to seed my production database with default values in some of the tables but when running my unit tests I want to add additional data and update some of the default values.

我已经创建一个自定义的Initializer类,它将数据库与默认值进行种子化。对于我的单元测试,我创建了另一个自定义的初始化器,继承自测试特定种子和/或修改的第一个:

I have created a custom Initializer class that seeds the database with the default values. For my unit tests I have created another custom Initializer that inherits from the first one that does the test specific seeding and/or modifications:

public class NerdDinnersInitializer : DropCreateDatabaseIfModelChanges<NerdDinners>
{
    protected override void Seed(NerdDinners context)
    {
        var dinners = new List<Dinner>
                          {
                              new Dinner()
                                  {
                                      Title = "Dinner with the Queen",
                                      Address = "Buckingham Palace",
                                      EventDate = DateTime.Now,
                                      HostedBy = "Liz and Phil",
                                      Country = "England"
                                  }
                          };

        dinners.ForEach(d => context.Dinners.Add(d));

        context.SaveChanges();
    }
}

public class NerdDinnersInitializerForTesting : NerdDinnersInitializer
{
    protected override void Seed(NerdDinners context)
    {
        base.Seed(context);

        var dinner = context.Dinners.Where(d => d.Country == "England").Single();
        dinner.Country = "Ireland";

        context.SaveChanges();
    }
}

我还使用基类进行单元测试初始化测试数据库,如下所示:

I also use a base class for my unit tests that initializes the test database like so:

[TestClass]
public abstract class TestBase
{
    protected const string DbFile = "test.sdf";
    protected const string Password = "1234567890";
    protected NerdDinners DataContext;

    [TestInitialize]
    public void InitTest()
    {
        Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0", "",
                string.Format("Data Source=\"{0}\";Password={1}", DbFile, Password));
        Database.SetInitializer(new NerdDinnersInitializerForTesting());

        DataContext = new NerdDinners();
        DataContext.Database.Initialize(true);
    }

    [TestCleanup]
    public void CleanupTest()
    {
        DataContext.Dispose();

        if (File.Exists(DbFile))
        {
            File.Delete(DbFile);
        }
    }
}

实际的单元测试看起来像这个:

The actual unit test looks like this:

[TestClass]
public class UnitTest1 : TestBase
{
    [TestMethod]
    public void TestMethod1()
    {
        var dinner = new Dinner()
                          {
                              Title = "Dinner with Sam",
                              Address = "Home",
                              EventDate = DateTime.Now,
                              HostedBy = "The wife",
                              Country = "Italy"
                          };

        DataContext.Dinners.Add(dinner);
        DataContext.SaveChanges();

        var savedDinner = (from d in DataContext.Dinners
                           where d.DinnerId == dinner.DinnerId
                           select d).Single();

        Assert.AreEqual(dinner.Address, savedDinner.Address);
    }
}

当我运行测试时,Linq查询获取savedDinner失败,并且ObjectContext实例已被处理,不能再用于需要连接的操作。例外。我不能解释为什么。

When I run the test the Linq query that fetches the savedDinner fails with the "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection." exception. I cannot work out why.

我在这里做的是可接受的模式,任何人都可以看出为什么这不起作用?

Is what I am doing here an acceptable pattern and can anyone shed some light as to why this is not working?

谢谢。

推荐答案

我今天早上碰到一个类似的问题。问题是由种子方法中的where子句引起的。这个(现在)的解决方法是重写:

I ran into a similar issue this morning. The problem is caused by the where clause in the seed method. A workaround for this (for now) is rewriting this:

var dinner = context.Dinners.ToList().Where(d => d.Country == "England").Single(); 

虽然效率不高(所有对象都从数据库检索,过滤将在内存中完成)在我的单元测试中解决了 ObjectDisposedException 。在我的情况下,我只有几个对象,所以我现在可以和它一起生活。

Although not efficient (all objects are retrieved from the database and filtering will be done in memory), it did solve the ObjectDisposedException in my unit tests. In my case I only have a few objects, so I can live with it for now.

这篇关于实体框架代码首先:如何种子数据库进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆