Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Sql CE 4数据库进行功能测试_C#_Unit Testing_Entity Framework 4_Functional Testing_Sql Server Ce - Fatal编程技术网

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

C# 如何使用Sql CE 4数据库进行功能测试,c#,unit-testing,entity-framework-4,functional-testing,sql-server-ce,C#,Unit Testing,Entity Framework 4,Functional Testing,Sql Server Ce,由于LINQtoEntities(EF4)和LINQtoObject之间的潜在差异,我需要使用实际的数据库来确保我的查询类正确地从EF检索数据。SQLCE4似乎是实现这一点的完美工具,但我遇到了一些问题。这些测试正在使用MsTest 我遇到的问题是,如果数据库没有重新创建(由于模型更改),那么每次测试后数据都会不断添加到数据库中,而没有任何东西会删除数据。这可能会导致测试中的冲突,查询返回的数据比预期的多 我的第一个想法是在TestInitialize方法中初始化TransactionScope

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

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

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

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

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

我已经没有办法有效地使用SQLCE4进行测试了。有人有更好的想法吗


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


最终编辑:在与Microsoft来回发送了一些电子邮件之后,结果表明,最新版本的SqlCE现在允许在SqlCE中使用
TransactionScope
s。但是,如果使用EF4,则存在一些限制,即在启动事务之前必须显式打开数据库连接。以下代码显示了一个sa有关如何成功使用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!
        }
    }

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

System.Data.Entity.Database.DbDatabase.SetInitializer<YourEntityFrameworkClass>(
    new System.Data.Entity.Database.DropCreateDatabaseAlways<YourEntityFrameworkClass>());
然后在初始化中,您将调用更改为:

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

我在“最终编辑”中找到了方法对我来说也很有用。但是,这真的很烦人。这不仅仅是为了测试,而且是任何时候你想使用TransactionScope with Entity Framework和SQL CE。我想编写一次代码,让我的应用程序同时支持SQL Server和SQL CE,但在我使用事务的任何地方,我都必须这样做。当然,Entity Framework团队应该为我处理这个问题我们

同时,我更进一步,使我的代码更加清晰

这使您在实际使用时更加干净:

using (var db = new MyDataContext())
{
    using (var ts = new TransactionScope())
    {
        // whatever you need to do

        db.SaveChanges();
        ts.Complete();
    }
}

虽然我认为,如果您的应用程序设计为在一次调用SaveChanges()中提交所有更改,那么隐式事务就足够了。对于测试场景,我们希望回滚所有内容,而不是调用ts.Complete(),所以它肯定是必需的。我肯定还有其他场景需要可用的事务范围。很遗憾,EF/SQLCE不直接支持它。

当然,SQL CE支持事务…但是使用TransactionScope是一种非常错误的方法。只需通过连接对象正常操作即可。我不确定如何使用E没有
TransactionScope
的F4实体,除非您的意思是不调用
SaveChanges()
,这意味着这些测试是无效的测试。您能提供一个如何使用Sql CE为数据播种的示例吗?我使用EF6,并希望使用Sql CEA对其进行测试在最终有机会检查后,这似乎不起作用。它似乎是在运行任何测试之前删除数据库,但不是在r之前删除数据库单独运行每个测试。这会导致数据在单元测试中持久化,导致其他一些测试失败。我现在可以解决这个问题,但我宁愿它在没有这个问题的情况下工作。不过,它太复杂了,不适合单元测试……我基本上使用它将多个表映射到单个实体,并在一个新的实体中完成每次我为那个特定的表调用它时都会进行组装…真的很难解释:)您不能在每次测试之后清除这些表并用seed方法重新填充它们吗?或者每个测试都是一组不同的表吗?有些测试我在测试用户查询,有些测试我在测试项目查询,等等。。因此,每个测试都使用不同的数据,因此我必须在每次测试后手动编写命令来清除每个表,随着我的应用程序的增长,这似乎需要大量的艰苦工作和维护,但这可能是唯一的方法(尽管这迫使我公开存储库中的所有方法)。当我开始编写更多基于聚合的测试(例如,在所有值中搜索关键字)时,我可以看到自己被测试之间的持久化数据烧坏了。我将您的帖子标记为解决方案,让您代表回来给我一些建议。根据你的建议,我找到了一个更可靠的解决方案,我把它放在了原来的帖子里!谢谢有趣的解决方案。我刚刚做了一个变通方法,我的
IUnitOfWork
类有一个
BeginTransaction()
EndTransaction(boolcommit)
方法
BeginTransaction
将打开连接,如果它没有
public MyDataContext()
{
    this.Connection.Open();
}

protected override void Dispose(bool disposing)
{
    if (this.Connection.State == ConnectionState.Open)
        this.Connection.Close();

    base.Dispose(disposing);
}

private DbConnection Connection
{
    get
    {
        var objectContextAdapter = (IObjectContextAdapter) this;
        return objectContextAdapter.ObjectContext.Connection;
    }
}
using (var db = new MyDataContext())
{
    using (var ts = new TransactionScope())
    {
        // whatever you need to do

        db.SaveChanges();
        ts.Complete();
    }
}