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

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

问题描述

我的问题和代码是基于代码第一个实体框架单元测试的例子的博客文章。我使用SQL精简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.

我创建一个自定义的初始化器类种子的默认值的数据库。对于我的单元测试我创建了从第一个,做测试的具体播种和/或修改继承另一个自定义初始化函数:

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查询获取的用的ObjectContext的实例已设置,不能再被用于需要连接的操作。savedDinner失败例外。我不明白为什么。

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天全站免登陆