集成测试数据库,我在做对吗? [英] Integration testing database, am I doing it right?

查看:183
本文介绍了集成测试数据库,我在做对吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要测试的依赖和使用数据库我MVC4应用方法。我不想用模拟的方法/对象,因为该查询可以复杂,创建测试对象,因为这是太多的努力。

我发现,在包装完成后回滚更改的的TransactionScope 对象测试的数据库操作逻辑集成测试的想法。

不幸的是,这并不起初一个空数据库开始,这也使得主键上数(即,当有已经与主键1和2中的数据库中的几个项目再经过运行测试它计数与4),我不想这样。

这是一个集成测试,我想出了只是为了测试,如果产品实际添加(例如,我希望创建一个检查方法,一旦我有权利的基础设施,更艰巨的考验)。

  [TestMethod的]
    公共无效ProductTest()
    {
        //安排
        使用(新的TransactionScope())
        {
            myContext DB =新myContext();
            产品testProduct =新产品
            {
                产品编号= 999999,
                类别ID = 3,
                ShopId = 2,
                价格= 1.00M,
                NAME =试验品,
                可见=真
            };            //法案
            db.Products.Add(testProduct);
            db.SaveChanges();            //断言
            Assert.AreEqual(1,db.Products.ToList()计数());
            //失败,因为有已在数据库中的物品        }    }

这引发了很多问题,这里有一个选择:我如何开始建立一个空数据库?我应该附加其他数据库的项目有自己的背景和连接字符串?而最重要的是,我该如何正确地测试,而不毁了我的旧数据一个实际的数据库上的方法?

我一直在忙了一整天试图找出如何单元/集成测试我的数据库逻辑。我希望有经验的开发人员可以在这里提供一些帮助!

/编辑的NDbUnit测试是否会影响/改变我的数据库...

 公共类IntegrationTests
{
    [测试方法]
    公共无效测试()
    {
        字符串的connectionString =数据源=(的LocalDB)\\\\ 11.0;初始目录= Database_Nieuw;
            集成安全性= FALSE;;
        //以上是唯一可行的ConnectionString的...而且是真正的本地数据库
        //这不是用在詹金斯,但我也许可以将其固定?
        NDbUnit.Core.INDbUnitTest mySqlDatabase =新
        NDbUnit.Core.SqlClient.SqlDbUnitTest(的connectionString);
        mySqlDatabase.ReadXmlSchema(@.. \\ .. \\ NDbUnitTestDatabase \\ NDbUnitTestDatabase.xsd);
        mySqlDatabase.ReadXml(@.. \\ .. \\ NDbUnitTestDatabase \\ DatabaseSeeding.xml); // 数据
        mySqlDatabase.PerformDbOperation(NDbUnit.Core.DbOperationFlag.CleanInsertIdentity);
}


解决方案

  

我不想用模拟的方法/对象,因为查询要复杂得多,创建测试对象,因为这是太多的努力。


这是正确的策略。最有趣的错误往往在客户code和(真正的)数据库之间的边界的出现。


  

我如何开始建立一个空数据库?


每次测试之前编程清除数据库。您可以通过将吹扫code标有<一的方法自动执行href=\"http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.testinitializeattribute%28v=vs.110%29.aspx\"相对=nofollow> [TestInitialize] 属性。如果您的数据库恰好ON DELETE CASCADE使用,删除所有数据可能会为少数删除顶表一样简单。

另外,只写你的测试是有弹性的情况下,已经有一个数据库中的某些数据。例如,每个测试将产生其自己的测试数据,并使用所产生的数据的的的特定的ID。这可以让你更好的性能,因为你不需要运行任何额外的清洗code。


  

和最重要的是,我该如何正确地测试,而不毁了我的旧数据一个实际的数据库上的方法?


忘掉它。从来没有在任何东西,但一个开发数据库根据需要,你可以扔掉的运行这样的测试。迟早你会犯一些你不打算,或者举行一些锁定生产(如通过击中在调试器断点)比接受更长时间​​,或者修改架构不兼容的方式,或者只是负载测试锤它的否则将影响实际用户的工作效率......

I want to test methods in my MVC4 application that rely on and work with a database. I do not want to use mock methods / objects because the queries can be complicated and creating test objects for that is too much of an effort.

I found the idea of integration testing that wraps your test's database manipulating logic in a TransactionScope object that rolls back the changes when done.

Unfortunately, this does not start with an empty database at first and it also makes the primary keys count on (i.e., when there are already a few items in the database with Primary keys 1 and 2 then after I run the test it counts on with 4), I do not want this.

This is an "integration test" I came up with just to test if products are actually added (an example, I want to create more difficult test that check the methods once I have the infrastructure right).

    [TestMethod]
    public void ProductTest()
    {
        // Arrange
        using (new TransactionScope())
        {
            myContext db = new myContext();
            Product testProduct = new Product
            {
                ProductId = 999999,
                CategoryId = 3,
                ShopId = 2,
                Price = 1.00M,
                Name = "Test Product",
                Visible = true
            };

            // Act
            db.Products.Add(testProduct);
            db.SaveChanges();

            // Assert
            Assert.AreEqual(1, db.Products.ToList().Count());
            // Fails since there are already items in database

        }

    }

This raises a lot of questions, here's a selection: How can I start with an empty database? Should I attach another database to the project with its own context and connection string? And most importantly, how do I properly test methods on an actual database without ruining my old data?

I have been busy all day trying to figure out how to unit/integration test my database logic. I hope some experienced developers here can provide some help!

/edit The NDbUnit test that DOES affect/change my database...

public class IntegrationTests
{
    [TestMethod]
    public void Test()
    {
        string connectionString = "Data Source=(LocalDb)\\v11.0;Initial Catalog=Database_Nieuw;
            Integrated Security=false;"; 
        //The above is the only connectionstring that works... And is the "real" local database
        //This is not used on Jenkins but I can perhaps attach it???
        NDbUnit.Core.INDbUnitTest mySqlDatabase = new 
        NDbUnit.Core.SqlClient.SqlDbUnitTest(connectionString);
        mySqlDatabase.ReadXmlSchema(@"..\..\NDbUnitTestDatabase\NDbUnitTestDatabase.xsd");
        mySqlDatabase.ReadXml(@"..\..\NDbUnitTestDatabase\DatabaseSeeding.xml"); // The data
        mySqlDatabase.PerformDbOperation(NDbUnit.Core.DbOperationFlag.CleanInsertIdentity);
}

解决方案

I do not want to use mock methods / objects because the queries can be complicated and creating test objects for that is too much of an effort.

This is the right strategy. Most "interesting" bugs tend to happen at the "boundary" between client code and the (real) database.

How can I start with an empty database?

Purge the database programmatically before each test. You can automate that by putting the purging code in a method marked with [TestInitialize] attribute. If your database happens to use ON DELETE CASCADE, deleting all data might be as simple as deleting few "top" tables.

Alternatively, just write your tests to be resilient in case there is already some data in the database. For example, each test would generate its own test data and use the specific IDs of the generated data only. This allows you better performance as you don't need to run any extra purging code.

And most importantly, how do I properly test methods on an actual database without ruining my old data?

Forget about it. Never run such tests on anything but a development database that you can throw-away as needed. Sooner or later you will commit something you did not intend to, or hold some lock longer than acceptable in production (e.g. by hitting a breakpoint in the debugger), or modify the schema in an incompatible manner, or just hammer it with load tests that would otherwise affect the productivity of real users...

这篇关于集成测试数据库,我在做对吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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