在Java环境中针对真实数据库架构的DAO敏捷集成测试的当前良好实践是什么?
('敏捷'是指这个问题最简化,自动化和简单的解决方案。)
我希望实现测试的自动化,证明数据访问层与数据库的实际运行实例无缝集成。我们针对特定供应商数据库测试自定义SQL非常重要。 I.E.如果我们编写T-SQL,我们想要针对SQL Server进行测试。
单个数据库是专用于所有正在运行的测试,但没有提交?或者每个测试环境是否都有专用数据库?
人们如何处理设置和拆解? DBUnit仍在流行使用吗?春天怎么能帮忙?
答案 0 :(得分:3)
我想说你的DAO集成测试只需要关注确保ORM的QL,例如HQL或JDBC SQL是有效的。我认为可以合理地假设查询语言本身已针对多个驱动程序/数据库进行了彻底测试。完成此操作后,使用HSQLDB等“内存”数据库是合理的。
“Spring Test”旨在进行集成测试,非常适合设置IoC上下文,提供事务,设置数据库会话,创建模式,然后在测试后删除它,在测试后回滚事务...因为我将我的一些数据库测试标记为集成测试(我个人认为,只要单元测试没有跨越进程边界并且它们的设置是无摩擦的,我们就坐在围栏上,它们构成了一个合理的单元测试)。
另一方面,一些好的系统测试应该测试您的系统端到端以及所有目标数据库。设置系统测试总是需要付出很多努力,因为您正在测试系统本身,所以在框架和工具包方面有很多帮助。
答案 1 :(得分:3)
我们必须针对特定供应商数据库测试自定义SQL
因此,您应该为每个供应商数据库创建一套测试
@RunWith(Suite.class)
@Suite.SuiteClasses({})
public class SQLServerTestSuite {
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
// clean database
}
}
单个数据库是专用于所有正在运行的测试,但没有提交?
建议您执行SQL命令但使用rollback命令,因为如果使用提交,您可以更改当前测试的状态以及更改其他测试的状态。否则,您可以处理意外行为。
对于每位开发者,建议使用database sandbox。这允许每个用户以他们认为合适的任何方式修改数据库,并使用测试来运行应用程序,而不必担心他们的测试与其他用户的测试之间的任何交互
人们如何处理设置和拆解?
public class PersonTest {
@Before
public void setUp() {
// set up state to run the test
}
@After
public void teardown() {
// Transaction rollback
}
}
关于Transaction rollback pattern的好处是它使数据库处于与我们开始测试时完全相同的状态,无论我们对数据库内容做了哪些更改
DBUnit仍在流行使用吗?
DBUnit用于将数据库表与包含的XML文件进行比较 预期值。您应该记住DBUnit处理手动编码设置。然而,虽然这种方法更彻底,但开发和维护这些类型的测试非常繁琐。此外,测试不会检测新添加的字段或属性的缺失映射。
Spring如何帮助?
Spring内置了对事务回滚模式的支持,并支持命名参数(SqlParameterSource),它允许您在每个供应商数据库的多行和可读xml文件中外部化普通jdbc查询,例如
<?xml version="1.0" encoding="UTF-8"?>
<queries>
<query name="PERSON_BY_ID">
<![CDATA[
select
*
from
PERSON
where
PERSON.ID = :integerId
]]>
</query>
</queries>
注意查询参数。它遵循JavaScript代码样式,您将参数类型声明为前缀。现在,您可以创建一个用于定义命名查询集的类
public class SQLServerQuery {
public static final String PERSON_BY_ID = "PERSON_BY_ID";
}
对于dinamic查询,通常重要的是检测查询逻辑中的错误,例如使用&lt;而不是&lt; = 。要捕获这些类型的错误,我们需要编写测试,用测试数据填充数据库,执行查询,并验证它是否返回预期的对象。不幸的是,这些类型的测试对于编写和执行都很耗时。
答案 2 :(得分:1)
我认为只要您确保拆除在测试开始时设置的数据,一个数据库(每个开发人员)应该没问题。如果您不依赖于任何初始数据集,则只需清理表即可。在这种情况下,DBUnit是一个很好的解决方案。
有时您依赖于一些初始数据集而不是所有测试,但主要针对选择查询的少数测试。如果您依赖某些数据集,那就变得棘手了。您仍然可以通过在每个测试开始之前运行种子数据并在结束时拆除来管理Dbunit,但它会使测试运行更长时间。
在这种情况下,我发现更好的是创建一个简单的实用程序类来保存在测试开始时创建的任何新数据的id,并在最后删除它。
答案 3 :(得分:0)
也许我不明白你想要做什么的目的或为什么选择这种测试方法,但是你考虑过使用模拟对象吗?您可以使用模拟对象编写Junits测试,并将其与Hudson集成以实现自动化。您可以模拟DAO,预备语句,连接,结果集等。
DAO是一种经过验证的模式。 JDBC或其他任何可用于连接的东西也是如此。你想证明它有效吗?或者你真的想在DAO的方法中测试查询或SQL吗?