我很好奇人们为单元测试数据访问类找到了什么策略,这些数据访问类不涉及为每个测试方法加载(并且可能是卸载)真实数据库?您是否使用模拟对象来表示数据库连接?如果是这样,您是否需要将模拟对象传递到每个测试方法中,从而强制API要求将真正的数据库连接作为每个方法的参数?或者,您是否将模拟对象传递给setup()中的构造函数?
我有一个实现我认为是数据映射器(或可能是网关)模式的类。它是负责封装SQL并返回(或保存)“业务对象”的类。其余代码可以与此映射器层和业务对象进行交互,完全忽略持久性模型。此代码需要在实际系统中拥有/维护或仅了解实时数据库连接。在测试中模拟这个很棘手。
问题是如何对这些映射器类中的一个进行单元测试。我最经常看到的在xUnit下创建单元测试的做法是使用测试的setup()方法来实例化SUT(被测系统),通常是您正在测试的对象,并将其存储在本地测试类中的变量。然后,每个测试方法都与该SUT的唯一实例进行交互。
但是,假设您在setup()方法中所做的任何事情都可能会在您的实际代码中的某处复制。因此,您必须将设置过程视为“这是我希望每次需要在现实世界中使用此对象时重复再现的内容。”如果我在设置中将数据库连接传递给映射器的构造函数,那很好,但这并不意味着每次我想真正使用一个时,我都必须将一个实时数据库连接传递给映射器对象的构造函数?想象一下,您将拥有需要检索或存储业务对象的各种场所,并且要使用数据映射器对象,您需要每次都传递数据库连接吗?
就我而言,我正在尝试为这些数据映射器对象建立测试,以实现以下目标:
我基本上看到了两个建议,将连接对象作为参数传递(我已经解决过)或者仅为测试扩展SUT类并覆盖现实世界中的任何数据库连接设置过程以使用模拟而不是系统。
我很好奇是否有其他人面对这些问题,使用任何语言,以及你为解决这些问题所做的工作?也许有一些明显的东西让我失踪了?
答案 0 :(得分:3)
根据我的经验,连接数据库的责任是数据访问的痛点。我通过让DAO根据配置文件(app.config等)处理它来解决这个问题。这样我写测试时就不用担心了。 DAL保留一个或多个数据库连接配置文件并在每次数据访问时连接/断开连接,因为最终连接池将负责物理连接/断开连接。
帮助我的另一件事是在运行测试之前使用dbUnit加载基线数据。我发现直接访问数据库而不是使用模拟对象更容易。此外,通过连接到一个真正的数据库,我可以(在某一点上)通过在不同的线程中发出命令来测试并发性 - 模拟对象不会给我真实的行为。
答案 1 :(得分:0)
您可以使用DbUnit来测试SQL
答案 2 :(得分:0)
这取决于你真正想要测试的内容。如果您想测试您的SQL是否符合您的预期,那么它确实会进入 Integration Test 领域。假设您正在使用Java,那么您可以使用几种纯Java RDBMS解决方案(Apache Derby,HSQLDB,H2)。
另一方面,如果您只是测试 Java< - > JDBC代码(即从ResultSets中读取),然后您可以模拟JDBC的几乎所有相关部分,因为它们主要是接口。 JMock对此非常有用。只需在您的受测试级别中添加setConnection()
方法,然后传入将进行出价的模拟java.sql.Connection
。这对于保持测试简短和甜蜜非常有效。
答案 3 :(得分:0)
根据数据库设置的复杂程度,使用内存存储可能是一个很好的选择。
通常我使用内存中的SQLite会话进行单元测试。这是完全成熟的数据库100%内存,没有文件,没有配置需要。只需一行。
现在这并不总是一个选择。 SQLite不支持完整服务器数据库的所有sql功能。通常我使用一层试图使我的代码数据库独立。在这些情况下,我只是切换到内存数据库实例,我在每个setUp / tearDown中快速创建/销毁内存。
您是否正在使用任何中间层来访问您的数据库?在大多数情况下,使用这种类型的中间件的最大好处不是数据库可移植性,而是简化的测试工具。