0

을 테스트하는 방법 :나는 봄 컨테이너에서 간단한 테스트를 가지고 EntityManager.persist() 호출

public class JpaCategoryRepositoryTest extends AbstractJpaJavaTestBase { 

    @Inject 
    private CategoryService categoryService; 

    @Test 
    public void testStoreCategory(){ 
     final Category category = new CategoryBuilder() 
       .name("Test category") 
       .build(); 
     assertEquals("Cateogory ID is not assigned", 0L, category.getId()); 
     categoryService.storeCategory(category); 
     assertNotEquals("Category ID is persistent", 0L, category.getId()); 
    } 
} 

assertNotEquals이 실패합니다. 그 거래가 아직 커밋되지 않았다고 생각했습니다. 그래, 나는 transactio 관리를 추가 테스트를 업데이 트했습니다 :

public class JpaCategoryRepositoryTest extends AbstractJpaJavaTestBase { 

    @Inject 
    private CategoryService categoryService; 

    @Inject 
    TransactionTemplate transactionTemplate; 

    @Test 
    public void testStoreCategory(){ 
     final Category category = new CategoryBuilder() 
       .name("Test category") 
       .build(); 
     assertEquals("Cateogory ID is not assigned", 0L, category.getId()); 
     transactionTemplate.execute(new TransactionCallback<Void>() { 
      @Override 
      public Void doInTransaction(TransactionStatus status) { 
       categoryService.storeCategory(category); 
       return null; 
      } 
     }); 
     assertNotEquals("Category ID is persistent", 0L, category.getId()); 
    } 
} 

하지만 도움이되지 않았습니다. 통합 테스트 중에 엔티티가 저장되었는지 테스트하는 가장 좋은 패턴은 무엇입니까? 테스트가 실패한 후 테이블을 확인할 때 실제 엔티티가 저장됩니다.

답변

1

JPA 사양에서 엔티티의 ID가 정확하게 설정되면 JPA 구현으로 남습니다. 그러나 엔티티가 데이터베이스에 기록 될 때 설정되어야합니다. entityManager.flush()를 호출하여이를 강제로 수행 할 수 있습니다.

@PersistenceContext 
private EntityManager entityManager; 

을하고 개체를 저장 한 후() 플러시 전화 : 그래서 테스트에 EntityManager를 추가

categoryService.storeCategory(category); 
entityManager.flush(); 

이 테스트를 해결해야한다.

은 참조 : When does the JPA set a @GeneratedValue @Id

+0

플러싱은 SQL 쿼리가 데이터베이스로 실행됨을 의미합니다. undestand correclty 인 경우, TransactionTemplate을 명시 적으로 사용할 때도 동일하게 보관됩니다. 그래서 아무런 차이가 보이지 않습니다. 어쨌든 당신의 솔루션을 시도했지만 예외가 있습니다 : "org.springframework.transaction.InvalidIsolationLevelException : 표준 JPA는 사용자 정의 격리 수준을 지원하지 않습니다 - JPA 구현을 위해 특별한 JpaDialect를 사용하십시오" – Alexandr

+0

유일한 방법은 엔티티의 ID는 데이터베이스에서 ID를 가져 오는 것입니다. 따라서 ID가 설정되었는지 확인하려면 데이터베이스에 대한 쿼리를 실행해야합니다 (메모리 내 데이터베이스 일 수도 있음). 예외는 구성의 격리 수준, 특히 단위 테스트에서 변경할 때 알려진 문제점입니다. https://jira.springsource.org/browse/SPR-5012 – Remco

+0

당신이 말하는 것에 대해 이해하지 못하는 것 같습니다. 먼저 플러시하는 것이 좋습니다. 그런 다음 ID를 얻는 유일한 방법은 쿼리를 실행하는 것입니다. 다음으로는 예외 솔루션에 대한 링크를 제공하지만 트랜잭션 당 특정 격리 수준을 설정하지 않습니다. – Alexandr

0

순간 난 그냥 지속 된 개체의 ID를 얻기 위해 해결책을 찾을 수 없습니다. id 생성 전략, jpa 제공자 등에 따라 달라질 수 있습니다.

엔티티가 지속되는지 테스트하기 위해 테스트 전과 트랜잭션 커밋 후에 번호 또는 레코드를 확인합니다. 테스트는 다음과 같이 나타납니다.

@Inject 
private CategoryService categoryService; 

@PersistenceContext 
private EntityManager entityManager; 

@Inject 
TransactionTemplate transactionTemplate; 

@Test 
public void testStoreCategory(){ 
    final Category category = new CategoryBuilder() 
      .name("Test category") 
      .build(); 
    assertEquals("The number of test categories loaded during initial setup is incorrect", 
      1, entityManager.createQuery("SELECT c FROM Category c").getResultList().size()); 
    assertEquals("Cateogory ID is not assigned", 0L, category.getId()); 
    transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
     @Override 
     protected void doInTransactionWithoutResult(TransactionStatus status) { 
      categoryService.storeCategory(category); 
     } 
    }); 
    assertEquals("The test category has not been persisted", 
      2, entityManager.createQuery("SELECT c FROM Category c").getResultList().size()); 
}