【问题标题】:Spring Boot Testing: JPA repository returning inconsistent dataSpring Boot 测试:JPA 存储库返回不一致的数据
【发布时间】:2021-06-24 07:05:13
【问题描述】:

我正在springboot中编写一些集成测试,以测试服务类中的业务逻辑。

测试步骤:

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() 应该返回修改后的数据

现实:返回的数据与初始数据相同

到目前为止我尝试和观察到的情况:

  1. 我尝试调试服务类,数据实际上正在获取 已修改并正确保存在数据库中,line c 处的代码仍然返回初始数据
  2. 如果我删除line aline b,那么line c 能够返回预期的修改数据

我在这里错过了什么吗?我如何在这里实现期望?

测试类:

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);

}

更新:初始数据和修改数据在同一版本

【问题讨论】:

  • 先问几个问题: 1. 你扩展的BaseIntegrationTest 是做什么的?存储库是否以某种方式在那里被操纵? 2. 为什么需要cleanup_scripts?如果这是一个标准的 Spring Boot JPA 集成测试,您只需在 beforeEachafterEach 的存储库中调用 deleteAll() 即可重置您的存储库。
  • 你的问题格式很好。但是正如您所说,quoteProductDelegate 上存在问题,它实际上修改并保存了数据。您认为将此类从您发布的代码中删除是一个好主意吗?
  • 你的版本逻辑很奇怪——如果它那么重要,你不会做任何操作来保存一个新版本吗?你的测试逻辑总是第一个?
  • @Lorenz G. 1. BaseIntegrationTest 是具有 springboottest 配置的类,每个测试类都在扩展。没有存储库调用存在there.2。是的,我们也可以使用 deleteAll()
  • @Boug,问题不在于服务类,它正在修改和保存正在保存的数据(也通过 H2 控制台检查)。问题是,如果我在测试开始时读取数据,那么第二次读取不起作用

标签: java spring spring-boot jpa spring-data


【解决方案1】:

我知道这里有什么问题。使用@Transactional 不知何故弄乱了我的测试。一旦我删除了事务性,它就起作用了。您可以阅读一篇很好的文章,了解为什么应该避免在春季测试中使用事务。

【讨论】:

    猜你喜欢
    • 2018-06-26
    • 2017-04-23
    • 2019-01-23
    • 2017-11-21
    • 2021-11-07
    • 1970-01-01
    • 2014-08-13
    • 1970-01-01
    • 2017-08-06
    相关资源
    最近更新 更多