Java DB单元测试框架?
在我的项目中,我使用了spring、jpa和PostgreSQL DB, 我有很多数据库中的表,我需要对它们进行单元测试 是否有任何框架可以在每个测试完成后回滚所有事务,以便每个测试都有新的/相同的DB数据进行测试。这样,在所有测试执行之后,DB模式的数据将保持原样 有什么建议吗 我对DBUnit有一些概念,但在这方面,我需要为每个测试的每个输入数据编写.xml文件,并且需要在setup()中插入数据,在tearDown()中清除/删除数据,但对我来说,这似乎不是更好的策略 如有任何建议,我们将不胜感激。Java DB单元测试框架?,java,unit-testing,spring,jpa,dbunit,Java,Unit Testing,Spring,Jpa,Dbunit,在我的项目中,我使用了spring、jpa和PostgreSQL DB, 我有很多数据库中的表,我需要对它们进行单元测试 是否有任何框架可以在每个测试完成后回滚所有事务,以便每个测试都有新的/相同的DB数据进行测试。这样,在所有测试执行之后,DB模式的数据将保持原样 有什么建议吗 我对DBUnit有一些概念,但在这方面,我需要为每个测试的每个输入数据编写.xml文件,并且需要在setup()中插入数据,在tearDown()中清除/删除数据,但对我来说,这似乎不是更好的策略 如有任何建议,我们将
谢谢。我已经按照以下方式处理了 当项目处于测试模式时。我使用bootstraping数据使用
dbdeploy
修复了可以断言的数据。并直接使用dao
测试应用程序的dao和DB层
希望能有帮助
更新
例如,在您的系统中有一个名为Person
的实体,现在您可以测试基本的CRUD操作
- 运行引导数据脚本来加载数据
- 从数据库中检索所有人员并对其进行断言。像智者一样看到所有的积垢
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
因此,它将回滚DB内容
是否有任何框架可以在每个测试完成后回滚所有事务,以便每个测试都有新的/相同的DB数据进行测试。这样,在所有测试执行之后,DB模式的数据将保持原样
从当天早些时候发布的消息来看,是的,这可以使用DbUnit实现。(根据您的编辑,您不需要这个;我的回答的后续部分将说明我为什么使用DbUnit,以及何时不使用它)
以下代码段演示了如何执行每个测试的设置:
@Before
public void setUp() throws Exception
{
logger.info("Performing the setup of test {}", testName.getMethodName());
IDatabaseConnection connection = null;
try
{
connection = getConnection();
IDataSet dataSet = getDataSet();
//The following line cleans up all DbUnit recognized tables and inserts and test data before every test.
DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);
}
finally
{
// Closes the connection as the persistence layer gets it's connection from elsewhere
connection.close();
}
}
private IDatabaseConnection getConnection() throws Exception
{
@SuppressWarnings({ "rawtypes", "unused" })
Class driverClass = Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection jdbcConnection = DriverManager.getConnection(jdbcURL, "XXX",
"YYY");
IDatabaseConnection databaseConnection = new DatabaseConnection(jdbcConnection);
return databaseConnection;
}
private IDataSet getDataSet() throws Exception
{
ClassLoader classLoader = this.getClass().getClassLoader();
return new FlatXmlDataSetBuilder().build(classLoader.getResourceAsStream("database-test-setup.xml"));
}
database test setup.xml
文件包含每次测试将插入数据库的数据。在设置
方法中使用DatabaseOperation.CLEAN_INSERT
可确保清除文件中指定的所有表格(通过删除所有行),然后在测试数据文件中插入指定数据
避免DbUnit
我使用上述方法专门在每个测试开始之前清除序列,因为应用程序使用JPA提供程序在单独的事务中更新序列。如果您的应用程序没有执行类似的操作,那么您只需在setup()
方法中启动一个事务,并在测试结束后发出一个回滚。如果我的应用程序没有使用序列(如果我不想重置序列),那么我的设置例程将非常简单:
@Before
public void setUp() throws Exception
{
logger.info("Performing the setup of test {}", testName.getMethodName());
// emf is created in the @BeforeClass annotated method
em = emf.createEntityManager();
// Starts the transaction before every test
em.getTransaction.begin();
}
@After
public void tearDown() throws Exception
{
logger.info("Performing the teardown of test {}", testName.getMethodName());
if (em != null)
{
// Rolls back the transaction after every test
em.getTransaction().rollback();
em.close();
}
}
另外,我使用Maven,但这主要是为了使测试数据库与版本化数据模型保持最新。正是为您这样做的。正如@Ryan所指出的。。。。应咨询专家 一些启动提示 我们使用Spring的
AbstractTransactionalJUnit4SpringContextTests
处理了这个问题
例如,我们定义了一个抽象超类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:WebContent/WEB-INF/testconfig/test-web-application-config.xml")
@TransactionConfiguration()
@Transactional
public abstract class OurAbstractTransactionalSpringContextTest extends AbstractTransactionalJUnit4SpringContextTests {
}
然后需要额外上下文的单个子类被定义为:
@ContextConfiguration("classpath:path/to/config/ConfigForTestCase.xml")
public class TestOurFunction extends OurAbstractTransactionalSpringContextTest {
@Test
public void testOurMethod() {
}
}
请注意:
@ContextConfiguration
forkmode=“perBatch”
属性。这确保所有测试都以相同的上下文配置运行(避免为每个测试重新加载Spring上下文)。您可以使用@DirtiesContext
指示应该在方法/类之后刷新上下文@Test
注释标记每个方法。Spring框架不会使用Junit的public void testXXX()
约定获取方法通过这种方式,由于数据未在数据库中提交,因此不会测试数据的持久性,并且可能不会引发一些违反约束的异常等。因此,这种与事务相关的方法似乎并不适合所有场景。您的意思是说,在不提交事务的情况下会引发违反约束的异常?如果是,我真的不知道这一点,你能给出一些想法吗?@JigarJoshi让我们感谢你的回答,这确实非常有用,但我认为对于第一种方法(DbUnit),在安装过程中的每个测试都会有数据插入的开销()例如,在许多测试中,我们需要来自一个或两个表的数据,但每次setup()都会插入所有表的数据。我认为第二种方法(事务)不会将数据保存在DB中(它不会实际持久化数据)所以DB不会抛出违反约束的异常,而且它似乎不适合所有场景的测试。如果我在这方面有错,请告诉我。@SmartSolution,您可以始终为每个夹具提供单独的XML文件。当然,如果夹具中的每个测试只需要一部分数据,并且这是一项开销,那么我建议使用。在约束违反和抛出异常的主题中,当您刷新“持久性文本”而不是“提交”时,将抛出持久性异常。@ StaskStudio,如果不刷新持久性上下文,则考虑更改存储库/ DAO类来执行此操作。如果有一组单元测试将在普通Java SE环境中创建持久性上下文并测试DAO/存储库行为,则可以避免这种情况——这不会测试事务传播等。这是正确的,但不是非常具体。参见雅各布的详细阐述。