Spring 启动测试:JPA 存储库返回不一致的数据
Spring Boot Testing: JPA repository returning inconsistent data
我正在用 springboot 编写一些集成测试,以测试服务中的业务逻辑 class。
测试步骤:
1. Inserting some initial data in inmemory db using sql scripts.
2. Asserting that the inserted data is correct using read operation on repository.
3. Executing the service class logic which reads the initial data and does some modification on it and save it through repository
4. Asserting that the initial data got modified after service class execution on reading the data again.
quoteProductDelegate 中的 Execute 方法对该初始数据进行必要的修改,并在 pricePlanDetailsRepo
上调用 save()
方法
期望:line c
即,第二次调用findByProductIdAndVersion()
应该return修改数据
现实: return编辑的数据与初始数据相同
到目前为止我尝试和观察到的:
- 我尝试调试服务 class,数据实际上正在获取
已修改并正确保存在数据库中,仍然是
line c
return 初始数据 处的代码
- 如果我删除
line a
和 line b
,那么 line c
能够 return 预期的修改数据
我在这里遗漏了什么吗?我如何达到这里的期望?
测试Class:
public class QuoteproductResourceWithOverrideRateCardTest extends BaseIntegrationTest
{
@Inject
private IQuoteProductDelegate quoteProductDelegate;
@Inject
private IPricePlanDetailsJpaRepository pricePlanDetailsRepo;
@Test
@Transactional
@Sql(
{ "/insert_initial_data.sql" })
@Sql(scripts = {"/cleanup_scripts"}, executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
public void rateCardFlagEnabledAndRateCardPresentCatalogVersioningOverrideMecCatalogPrice() throws Exception
{
a ---- PricePlan initialPricePlanData = pricePlanDetailsRepo.findByProductIdAndVersion("Product_59",1L);
b ---- Assert.assertEquals(4000, initialPricePlanData.getAmount(), 0.1d);
initialPricePlanData = null;
Response response = quoteProductDelegate.execute(parameters);
c ---- PricePlan modifiedPricePlan = pricePlanDetailsRepo.findByProductIdAndVersion("Product_59",1L);
Assert.assertEquals(10000, modifiedPricePlan.getAmount(), 0.1d);
}
}
存储库:
@ConditionalOnProperty(value = "oracle.enabled", havingValue = "true", matchIfMissing = true)
@Repository
public interface IPricePlanDetailsJpaRepository extends JpaRepository<PricePlan, String>
{
@Query("SELECT p FROM PricePlan p WHERE p.rootId = ?1 and p.rootVersion = (SELECT MAX(q.rootVersion) FROM PricePlan q WHERE q.rootId = ?1 AND q.rootVersion <= ?2)")
PricePlan findByProductIdAndVersion (@Param("productId") String productId, @Param("rootVersion") Long version);
}
更新:初始数据和修改后的数据是同一个版本
我想通了这里的问题是什么。使用 @Transactional
不知何故搞乱了我的测试。一旦我删除了交易,它就起作用了。您可以阅读一篇很好的文章,了解为什么应避免在 spring 测试中使用事务。
我正在用 springboot 编写一些集成测试,以测试服务中的业务逻辑 class。
测试步骤:
1. Inserting some initial data in inmemory db using sql scripts.
2. Asserting that the inserted data is correct using read operation on repository.
3. Executing the service class logic which reads the initial data and does some modification on it and save it through repository
4. Asserting that the initial data got modified after service class execution on reading the data again.
quoteProductDelegate 中的 Execute 方法对该初始数据进行必要的修改,并在 pricePlanDetailsRepo
save()
方法
期望:line c
即,第二次调用findByProductIdAndVersion()
应该return修改数据
现实: return编辑的数据与初始数据相同
到目前为止我尝试和观察到的:
- 我尝试调试服务 class,数据实际上正在获取
已修改并正确保存在数据库中,仍然是
line c
return 初始数据 处的代码
- 如果我删除
line a
和line b
,那么line c
能够 return 预期的修改数据
我在这里遗漏了什么吗?我如何达到这里的期望?
测试Class:
public class QuoteproductResourceWithOverrideRateCardTest extends BaseIntegrationTest
{
@Inject
private IQuoteProductDelegate quoteProductDelegate;
@Inject
private IPricePlanDetailsJpaRepository pricePlanDetailsRepo;
@Test
@Transactional
@Sql(
{ "/insert_initial_data.sql" })
@Sql(scripts = {"/cleanup_scripts"}, executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
public void rateCardFlagEnabledAndRateCardPresentCatalogVersioningOverrideMecCatalogPrice() throws Exception
{
a ---- PricePlan initialPricePlanData = pricePlanDetailsRepo.findByProductIdAndVersion("Product_59",1L);
b ---- Assert.assertEquals(4000, initialPricePlanData.getAmount(), 0.1d);
initialPricePlanData = null;
Response response = quoteProductDelegate.execute(parameters);
c ---- PricePlan modifiedPricePlan = pricePlanDetailsRepo.findByProductIdAndVersion("Product_59",1L);
Assert.assertEquals(10000, modifiedPricePlan.getAmount(), 0.1d);
}
}
存储库:
@ConditionalOnProperty(value = "oracle.enabled", havingValue = "true", matchIfMissing = true)
@Repository
public interface IPricePlanDetailsJpaRepository extends JpaRepository<PricePlan, String>
{
@Query("SELECT p FROM PricePlan p WHERE p.rootId = ?1 and p.rootVersion = (SELECT MAX(q.rootVersion) FROM PricePlan q WHERE q.rootId = ?1 AND q.rootVersion <= ?2)")
PricePlan findByProductIdAndVersion (@Param("productId") String productId, @Param("rootVersion") Long version);
}
更新:初始数据和修改后的数据是同一个版本
我想通了这里的问题是什么。使用 @Transactional
不知何故搞乱了我的测试。一旦我删除了交易,它就起作用了。您可以阅读一篇很好的文章,了解为什么应避免在 spring 测试中使用事务。