Testing 如何在测试后回滚特定记录?
我有一个修改一些数据库内容的spock/spring测试,我想知道如何回滚该记录 目前,我执行一个原始sql语句,保存字段数据,并在测试成功后恢复该数据。但我猜这可以用一种更简单的方法来实现Testing 如何在测试后回滚特定记录?,testing,groovy,spock,Testing,Groovy,Spock,我有一个修改一些数据库内容的spock/spring测试,我想知道如何回滚该记录 目前,我执行一个原始sql语句,保存字段数据,并在测试成功后恢复该数据。但我猜这可以用一种更简单的方法来实现 @ContextConfiguration(locations = "classpath*:applicationContext-test.xml") class RepositoryTest extends Specification { @Shared sql = Sql.
@ContextConfiguration(locations = "classpath*:applicationContext-test.xml")
class RepositoryTest extends Specification {
@Shared sql = Sql.newInstance("jdbc:sqlserver://...")
ResourceRepository resourceRepository;
def "Save test"() {
setup:
// copy the row before we do changes! we need to restore this later on!
def row = sql.firstRow("select id, content, status from table-name where id = 12345")
when:
...
then:
..
cleanup:
sql.execute("""
update table-name set content = ${row.content}, status = ${row.status}
where id = ${row.id}
""")
}
}
在运行测试之前,将此选择产生的字符串存储在VARCHAR2(4000)变量中,测试之后,您只需执行该字符串:
SELECT 'UPDATE TABLE_NAME SET CONTENT = '
|| CONTENT
|| ', STATUS = '
|| STATUS
|| ' WHERE ID = '
|| ID
FROM TABLE_NAME
WHERE ID = 1;
在上一个示例中,我假设要备份的记录的ID为1。
在本例中,字符串包含以下UPDATE语句:
UPDATE TABLE_NAME SET CONTENT = 2, STATUS = 3 WHERE ID = 1
我发现最好的方法是:
- 启动测试
- 启动事务
- (可选)使用类似DBUnit的内容加载测试所需的任何DB数据
- 运行测试
- 回滚事务
AbstractTransactionalJUnit4S普林gContextTests
// Location of the Spring config file(s)
@ContextConfiguration(locations = {"/application-context-test.xml", "classpath*:/application-context-persistence-test.xml"})
// Transaction manager bean name
@TransactionConfiguration(transactionManager = "hsqlTransactionManager", defaultRollback = true)
@Transactional(propagation=Propagation.REQUIRES_NEW)
public class MyTransactionalTests extends AbstractTransactionalJUnit4SpringContextTests {
@Test
public void thisWillRunInATransactionThatIsAutomaticallyRolledBack() {}
}
如果不想扩展Spring类,可以使用注释配置测试运行程序。Spring还支持许多其他主要的单元测试框架和较旧版本的JUnit。如果您在测试中将Groovy的Sql与Spring的注释(@RunWith、@ContextConfiguration、@Transactional、@Rollback,…)混合使用,您可能希望使用org.springframework.jdbc.dataSource.TransactionAwareDataSourceProxy包装数据源
<bean id="db-dataSourceReal"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/foo" />
<property name="resourceRef" value="true" />
<property name="lookupOnStartup" value="true" />
</bean>
<bean id="db-dataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="db-dataSourceReal" />
</bean>
您真的想回滚特定的记录,而不是测试方法所做的任何事情吗?因为Spock直接支持Spring的TestContext框架,所以您既不需要基类也不需要自定义运行程序@为了将bean命名为“transactionManager”,可以省略TransactionConfiguration。要使Groovy的Sql类与Spring的事务一起工作,必须使用Spring提供的数据源对其进行初始化。Sql类不执行异常转换这一事实可能会影响在何种情况下回滚事务。
<bean id="db-dataSourceReal"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/foo" />
<property name="resourceRef" value="true" />
<property name="lookupOnStartup" value="true" />
</bean>
<bean id="db-dataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="db-dataSourceReal" />
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations=[
"classpath*:applicationContext-test.xml"
])
class SimplePojoDaoIT {
@Resource(name="dao-pojoDao")
PojoDao pojoDao
@Test
@Transactional("transactionManager")
@Rollback
public void testShouldPersistToDB(){
SomePojo pojo = new SomePojo()
pojo.with{
id = 5
name = 'foo'
}
pojoDao.persist(pojo)
def sql = new Sql(pojoDao.dataSource)
sql.rows("select * from POJO_TBL where id = :id", [['id':pojo.id]]).each{ row ->
// println row
pojo.with{
assertEquals(id, row.ID.longValue())
assertEquals(name, row.NAME)
}
}
}
}