Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.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
Database 如何使用数据库查询对对象进行单元测试_Database_Unit Testing - Fatal编程技术网

Database 如何使用数据库查询对对象进行单元测试

Database 如何使用数据库查询对对象进行单元测试,database,unit-testing,Database,Unit Testing,我听说单元测试“非常棒”、“非常酷”和“各种各样的好东西”,但我的70%或更多的文件都涉及数据库访问(一些是读的,一些是写的),我不知道如何为这些文件编写单元测试 我正在使用PHP和Python,但我认为这是一个适用于大多数/所有使用数据库访问的语言的问题。理想情况下,您的对象应该是持久的。例如,您应该有一个“数据访问层”,您可以向其发出请求,并返回对象。通过这种方式,您可以将该部分从单元测试中排除,或者单独测试它们 如果对象与数据层紧密耦合,则很难进行适当的单元测试。单元测试的第一部分是“单元

我听说单元测试“非常棒”、“非常酷”和“各种各样的好东西”,但我的70%或更多的文件都涉及数据库访问(一些是读的,一些是写的),我不知道如何为这些文件编写单元测试


我正在使用PHP和Python,但我认为这是一个适用于大多数/所有使用数据库访问的语言的问题。

理想情况下,您的对象应该是持久的。例如,您应该有一个“数据访问层”,您可以向其发出请求,并返回对象。通过这种方式,您可以将该部分从单元测试中排除,或者单独测试它们


如果对象与数据层紧密耦合,则很难进行适当的单元测试。单元测试的第一部分是“单元”。所有装置应能够进行隔离测试

在我的c#项目中,我使用NHibernate和一个完全独立的数据层。我的对象位于核心域模型中,可以从我的应用程序层访问。应用程序层与数据层和域模型层进行对话

应用层有时也称为“业务层”

如果您使用的是PHP,请仅为数据访问创建一组特定的类。确保您的对象不知道它们是如何持久化的,并在您的应用程序类中将它们连接起来


另一个选项是使用mock/stubs。

如果要对类进行单元测试,则应该模拟数据库访问。毕竟,您不希望在单元测试中测试数据库。这将是一个集成测试


抽象掉调用,然后插入一个只返回预期数据的模拟。如果您的类只执行查询,那么甚至不值得测试它们,尽管…

我通常尝试在测试对象(以及ORM,如果有的话)和测试db之间分离测试。我通过模拟数据访问调用来测试事物的对象端,而我通过测试与db的对象交互来测试事物的db端,根据我的经验,db通常是相当有限的


我曾经对编写单元测试感到沮丧,直到我开始模拟数据访问部分,这样我就不必创建测试数据库或动态生成测试数据。通过模拟数据,您可以在运行时生成所有数据,并确保对象在已知输入下正常工作。

您可以使用模拟框架来抽象出数据库引擎。我不知道PHP/Python是否有一些,但对于类型化语言(C#、Java等),有很多选择


这还取决于您如何设计这些数据库访问代码,因为有些设计比前面的文章提到的其他设计更容易进行单元测试。

我从未在PHP中这样做过,也从未使用过Python,但您要做的是模拟对数据库的调用。要做到这一点,您可以实现一些第三方工具,或者您自己管理它,然后您可以实现数据库调用方的一些模拟版本,您将在其中控制假调用的结果

一种简单的IoC形式可以通过对接口进行编码来实现。这需要在代码中进行某种面向对象的操作,因此它可能不适用于您所做的事情(我说,因为我所要做的就是您提到的PHP和Python)


希望这会有所帮助,如果你现在没有其他的搜索条件的话。

我同意第一个后期数据库访问应该剥离到实现接口的DAO层中。然后,您可以针对DAO层的存根实现测试您的逻辑。

这本书描述了处理命中数据库的单元测试代码的一些方法。我同意其他人的说法,你不想这样做是因为它很慢,但你总有一天会这么做的,我想。模拟db连接来测试更高级别的东西是个好主意,但是,看看这本书,你可以做些什么来与实际的数据库进行交互。如果你的项目具有高度的内聚性和松散耦合性,那么单元测试你的数据库访问就足够容易了。通过这种方式,您可以只测试每个特定类所做的事情,而不必同时测试所有内容

例如,如果您对用户界面类进行单元测试,那么您编写的测试应该只验证UI内部的逻辑是否按预期工作,而不是验证该函数背后的业务逻辑或数据库操作

如果您想对实际的数据库访问进行单元测试,那么实际上最终将进行更多的集成测试,因为您将依赖于网络堆栈和数据库服务器,但是您可以验证您的SQL代码是否执行了您要求它执行的操作

单元测试对我个人来说隐藏的力量是它迫使我以一种比没有它们时更好的方式设计我的应用程序。这是因为它真的帮助我摆脱了“这个功能应该做一切”的心态

很抱歉,我没有PHP/Python的任何特定代码示例,但是如果您想查看.NET示例,我有一个描述我用于执行相同测试的技术的示例。

您有以下选项:

  • 编写一个脚本,在开始单元测试之前清除数据库,然后用预定义的数据集填充数据库并运行测试。您也可以在每次测试之前这样做,这样做会很慢,但不太容易出错
  • 注入数据库。(伪Java示例,但适用于所有OO语言) class Database { public Result query(String query) {... real db here ...} }

    class MockDatabase extends Database { public Result query(String query) { return "mock result"; } }

    class ObjectThatUsesDB { public ObjectThatUsesDB(Database db) { this.database = db; } } 类数据库{ 公共结果查询(字符串查询){…real db here…} }

    类MockDatabase扩展数据库{ 公共结果查询(字符串查询){ 返回“模拟结果”; } }

    使用SDB的类对象{ 使用SDB(数据库db)的公共对象{ this.database=db; } } 现在在生产环境中,您使用普通数据库,对于所有测试,您只需注入模拟数据库即可创建临时数据库

  •     [Test]
        [ExpectedException(typeof(NotFoundException))]
        public void DeleteAttendee() {
    
            using(TransactionScope scope = new TransactionScope()) {
                Attendee anAttendee = Attendee.Get(3);
                anAttendee.Delete();
                anAttendee.Save();
    
                //Try reloading. Instance should have been deleted.
                Attendee deletedAttendee = Attendee.Get(3);
            }
        }