簡體   English   中英

Spring-Data/Spring-Boot 下單元測試中的 LazyInitializationException

[英]LazyInitializationException in unit tests under Spring-Data/Spring-Boot

我的單元測試看到org.hibernate.LazyInitializationException: could not initialize proxy [org.openapitools.entity.MenuItem#5] - no Session 我不確定他們為什么希望在單元測試中使用 session。 我正在嘗試寫入內存中的 h2 數據庫,以對實現 RESTful API 的 Controller 類進行單元測試。 我沒有使用任何模擬對象進行測試,因為我想測試實際的數據庫事務。 這在我使用 Spring-Boot 版本 1.x 時效果很好,但是當我移到版本 2 時就壞了。(我不確定這是否是導致測試中斷的原因,因為我做了很多其他更改。我的意思是我的代碼已經通過了這些測試。)

我的存儲庫擴展了 JPARepository,所以我使用標准的 Hibernate 接口。

StackOverflow 上有很多關於這個問題的答案,但很少有人描述我可以與 Spring-Data 一起使用的解決方案。

附錄:下面看一下單元測試:

@Test
public void testDeleteOption() throws ResponseException {
  MenuItemDto menuItemDto = createPizzaMenuItem();
  ResponseEntity<CreatedResponse> responseEntity 
      = adminApiController.addMenuItem(menuItemDto);
  final CreatedResponse body = responseEntity.getBody();
  assertNotNull(body);

  Integer id = body.getId();
  MenuItem item = menuItemApiController.getMenuItemTestOnly(id);
  // Hibernate.initialize(item); // attempted fix blows up
  List<String> nameList = new LinkedList<>();
  for (MenuItemOption option : item.getAllowedOptions()) { // blows up here
    nameList.add(option.getName());
  }
  assertThat(nameList, hasItems("pepperoni", "olives", "onions"));
  // ... (more code)
}

我的測試 application.properties 有這些設置

spring.datasource.url=jdbc:h2:mem:pizzaChallenge;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=pizza
spring.datasource.password=pizza
spring.jpa.show-sql=true

這不是標准的 Hibernate,而是 spring 數據。 您必須了解 Hibernate 使用延遲加載來避免從數據庫中加載整個 object 圖。 如果您關閉 session 或連接到數據庫,例如通過結束事務,Hibernate 不能再延遲加載,顯然,您的代碼會嘗試訪問需要延遲加載的 state。

您可以在存儲庫上使用@EntityGraph來指定應獲取關聯,或者避免訪問未在事務之外初始化的 state。 也許您只需要通過將@Transactional放在調用存儲庫並訪問state 的方法上來擴大事務scope,以便延遲加載工作。

我找到了解決這個問題的方法。 我不確定這是否是最好的方法,所以如果有人有更好的想法,我會很高興收到他們的來信。

這就是我所做的。 首先,在從延遲加載的實體中讀取值之前,我調用Hibernate.initialize(item);

這會引發相同的異常。 但是現在我可以在 application.properties 的測試版本中添加一個屬性,上面寫着

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

現在初始化方法將起作用。

PS 我還沒有找到像這樣的 Spring 屬性的良好參考。 如果有人知道我在哪里可以看到可用的屬性,我很想聽聽。 Spring 的人員在記錄這些屬性方面做得不是很好。 即使他們提到了一個特定的屬性,他們也沒有提供一個可以更徹底地解釋它的鏈接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM