Spring的声明式事务管理是通过Spring AOP实现的,这种方式对代码的侵入性最小,可以让事务管理代码完全从业务代码中移除,如下图所示,只要是ItemManagerTx类中含有*InTx 的方法,Spring都会对这些方法中的事务进行管理。
Spring的声明式事务管理中具有回滚规则,可以在配置文件中通过声明的方式指定哪种异常导致自动回滚,哪种异常不影响事务提交。如下图所示。
由于使用了Spring的声明式事务管理,业务代码中通过取合适的事务模板进行数据库的操作,在进行事务接口的测试要非常仔细,首先需要了解所测的接口涉及到是单个事务还是多个事务,(1)当接口涉及的是单个事务操作同一个库的不同表时,正常流测试用例:执行第1个业务逻辑插入数据到第1张表成功,执行第2个业务逻辑成功的测试场景,校验两张表的数据都操作成功。异常流测试用例:执行第1个业务逻辑插入数据到第1张表成功,执行第2个业务逻辑失败的测试场景,校验测试结果的重点是第1张表的数据会回滚。(2)当接口涉及的是多个事务操作不同库不同表时,正常流测试用例:执行第1个成功了再进行下一个,下一个成功了则一起提交,验证数据都操作成功。异常流测试用例:执行第1个成功了再进行下一个,下一个失败了则同时回滚的场景,校验数据都没有操作成功。由于有些异常的场景很难通过业务用例去覆盖,然后要能过接口去模拟这种场景从而测到事务是否回滚,我采用的是mock的方式,如下所示:
try { itemBidServiceImpl.setItemManager(new ItemManagerImpl(){ @Override public boolean updateQuantityAndPriceAndSku(参数1,参数2) throws Exception { return false ; } }); ——(步骤 1) ResultDO result = itemBidServiceClient.updateAuctionQuantityAndSku(参数1,参数2); Assert.assertNotNull(result); ResultAssert.assertFalse(result); ResultDO<ItemDO> resultDO = itemQueryService.queryItemForDetail(itemId); ResultAssert.assertTrue(resultDO); Assert.assertEquals(2, resultDO.getModule().getSkuList().get(0).getQuantity()); —(步骤2) } finally { itemBidServiceImpl.setItemManager(itemManager); —–(步骤3) } |
步骤1:通过业务场景很难模拟itemBidServiceImpl 类中的updateQuantityAndPriceAndSku方法返回false,所以我通过在测试脚本中mock此方法,让程序调用到此方法时直接返回false。
步骤2:由于步骤1返回false,则updateAuctionQuantityAndSku接口应该事务回滚,所以在此步是做校验的工作,验证在执行步骤1之前操作过数据库的数据是否已经回滚了。
步骤3:所有测试用例都会放到hudson持续集成测试环境执行,通过finally可以将真实的itemManager设回去,因为不会因为之前mock了 itemManager而影响到其他测试用例。