在我的项目中,我使用了spring,jpa和PostgreSQL DB, 我在DB中有很多表,我需要对所有这些表进行单元测试。
是否有任何框架在每次测试完成后回滚所有事务,因此每个测试都会有新的/相同的DB数据进行测试。这种方式在所有测试执行之后,数据库模式的数据将保持不变。
对此有何建议?
我对DBUnit有所了解,但我需要为每个测试编写每个输入数据的.xml文件,需要在setup()中插入数据并清除/删除tearDown()中的数据,但不是对我来说似乎是更好的策略。
任何建议表示赞赏。 感谢。
答案 0 :(得分:4)
正如@Ryan表示......应该咨询Testing section of the Spring Reference manual。
一些启动提示......
我们使用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"
任务上的junit
属性。这可确保所有测试都使用相同的上下文配置运行(从每次测试的重新加载Spring上下文中省去)。您可以使用@DirtiesContext
指示应在方法/类之后刷新上下文。@Test
注释标记每个方法。 Spring框架没有使用Junit的public void testXXX()
约定来获取方法。答案 1 :(得分:3)
是否有任何框架在每次测试完成后回滚所有事务,因此每个测试都会有新的/相同的DB数据进行测试。这种方式在所有测试执行之后,数据库模式的数据将保持不变。
从当天早些时候发布的my other answer开始,是的,这可以使用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
方法中使用setup
可确保清除文件中指定的所有表(通过删除所有行),然后在测试数据文件中插入指定的数据。
避免使用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中使用dbdeploy,但这主要是为了使测试数据库与版本化数据模型保持同步。
答案 2 :(得分:2)
Spring's test framework完全适合你。
答案 3 :(得分:0)
我按照方式处理了它。
项目处于测试模式时。我使用bootstraping数据来测试dbdeploy
修复了您可以断言的数据。并直接使用dao
来测试应用程序的DAO和DB层。
希望有所帮助
<强>更新强>
例如,您的系统中有一个名为Person
的实体,现在您可以测试的是基本的CRUD操作。
回滚您可以标记的交易
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
所以它会回滚数据库的东西