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
Unit testing 单元测试DAO时使用模拟对象的策略_Unit Testing_Testing_Tdd_Mocking - Fatal编程技术网

Unit testing 单元测试DAO时使用模拟对象的策略

Unit testing 单元测试DAO时使用模拟对象的策略,unit-testing,testing,tdd,mocking,Unit Testing,Testing,Tdd,Mocking,我很好奇,人们在单元测试数据访问类时发现了什么策略,而这些数据访问类不涉及为每个测试方法加载(并可能卸载)真实数据库?您是否使用模拟对象来表示数据库连接?如果是这样的话,您是否需要将模拟对象传递到每个被测试的方法中,从而迫使API需要一个真正的db连接作为每个方法的参数?或者,是否将模拟对象传递到setup()的构造函数中 我有一个类正在实现我认为是数据映射器(或者网关)模式的东西。它是负责封装SQL并返回(或保存)“业务对象”的类。代码的其余部分可以与这个映射器层和业务对象交互,而完全不考虑持

我很好奇,人们在单元测试数据访问类时发现了什么策略,而这些数据访问类不涉及为每个测试方法加载(并可能卸载)真实数据库?您是否使用模拟对象来表示数据库连接?如果是这样的话,您是否需要将模拟对象传递到每个被测试的方法中,从而迫使API需要一个真正的db连接作为每个方法的参数?或者,是否将模拟对象传递到setup()的构造函数中

我有一个类正在实现我认为是数据映射器(或者网关)模式的东西。它是负责封装SQL并返回(或保存)“业务对象”的类。代码的其余部分可以与这个映射器层和业务对象交互,而完全不考虑持久性模型。这段代码需要在实际系统中拥有/维护或只知道实时数据库连接。在测试中模拟这一点是很棘手的

问题是如何对这些映射器类中的一个进行单元测试。我经常看到的在xUnit下创建单元测试的实践是使用测试的setup()方法实例化SUT(测试中的系统),通常是您正在测试的对象,并将其存储在测试类中的局部变量中。然后,每个测试方法都与该SUT的唯一实例交互

不过,我们的假设是,不管您在setup()方法中做什么,都可能会复制到实际代码的某个地方。因此,您必须将设置过程视为“这是否是我每次需要在现实世界中使用此对象时都要重复复制的内容。”如果我在设置中将db连接传递到映射器的构造函数中,这很好,但这不意味着每次我真的想使用一个实时db连接时,我都必须将一个实时db连接传递到mapper对象的构造函数中吗?假设您将有各种各样的地方需要检索或存储业务对象,而要使用数据映射器对象,您每次都需要传入db连接

在本例中,我尝试为这些数据映射器对象建立测试,以实现以下目标:

  • 不需要实例化数据库连接对象并将其传递到mapper类的每个方法中
  • 不要求测试用例为每个测试方法连接到一个真实的db或创建一个真实的但“测试”的db
  • 我基本上看到了两个建议,将connection对象作为参数传递(我已经提到了),或者扩展SUT类只是为了测试,并覆盖现实世界中的任何db连接设置过程,以使用模拟系统


    我很好奇,是否还有其他人用任何语言面对这些问题,你做了什么来解决它们?也许我缺少了一些明显的东西?

    根据我的经验,连接数据库的责任是数据访问中的一个痛处。我通过让DAO根据配置文件(app.config等)处理这个问题来解决这个问题。这样,当我编写测试时,我就不必担心这个问题。DAL保留一个或多个数据库连接配置文件,并在每次数据访问时连接/断开连接,因为最终连接池将负责物理连接/断开连接


    另一件帮助我的事情是在运行测试之前使用dbUnit加载基线数据。我发现直接进入数据库比使用模拟对象更容易。另外,通过连接到真实的数据库,我可以(在某一点上)通过在不同的线程中发出命令来测试并发性—模拟对象不会给出真实的行为。

    您可以使用DbUnit测试SQL

    这取决于您真正要测试的内容。如果您想测试您的SQL是否达到了预期的效果,那么这实际上就是进入集成测试领域。假设您使用的是Java,那么您可以使用几个纯Java RDBMS解决方案(ApacheDerby、HSQLDB、H2)


    另一方面,如果您真的只是测试Java JDBC代码(即从结果集读取),那么您可以模拟JDBC的几乎所有相关部分,因为它们主要是接口。这很好。只需在测试的类中添加一个
    setConnection()
    方法,并通过模拟的
    java.sql.Connection
    即可。这对于保持测试的简短性非常有效。

    根据数据库设置的复杂程度,使用内存存储可能是一个不错的选择

    通常我使用内存中的SQLite会话进行单元测试。这是完全成熟的数据库,100%内存,无需文件,无需配置。就一行

    现在,这并不总是一种选择。SQLite不支持完整服务器数据库的所有sql功能。通常,我使用一个层,试图使我的代码数据库独立。在这些情况下,我只是切换到内存中的数据库实例,在每次安装/拆卸过程中,我都会在内存中快速创建/销毁该实例

    您是否使用中间层访问数据库?在大多数情况下,使用这种中间件的最大好处不是数据库的可移植性,而是简化的测试工具