什么时候在测试中强制使用 TestEntityManager?
When is mandatory use TestEntityManager in testing?
有一个 Spring 引导应用程序,使用 Spring 配置的数据 JPA 和 H2,它用于 sample/academic 目的。
存储库定义为:
public interface PersonaRepository extends CrudRepository<Persona, String> {
}
然后是下面的测试
@ActiveProfiles(profiles={"h2"})
@DataJpaTest
class PersonaRepositorySliceTests {
@Autowired
private PersonaRepository personaRepository;
@Autowired
private TestEntityManager testEntityManager;
@Test
void countTest() {
long count = personaRepository.count();
assertThat(count).isEqualTo(33);
count = testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Persona p")
.getResultList().size();
System.out.println("count: " + count);//prints 1
//assertThat(count).isEqualTo(33);//fails
count = testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM persona")
.getResultList().size();
System.out.println("count: " + count);//prints 1
assertThat(count).isEqualTo(33);//fails
}
}
long count = personaRepository.count();
assertThat(count).isEqualTo(33);
通过,因此检测到 @Entity
类,当然 schema-h2.sql
和 data-h2.sql
脚本也按预期执行。
现在的困惑是为什么
.createQuery("SELECT COUNT(*) FROM Persona p")
.createNativeQuery("SELECT COUNT(*) FROM persona")
有效 但 总是 returns 1,为什么不是 33 如何预期?
“似乎” TestEntityManager
在某种程度上 而不是 使用 [=15= 加载的数据] 文件。
二级问题:
- 这是预期的行为吗?
即使是,为什么返回1而不是0?还是强制性的额外配置?
看了一些关于@DataJpaTest
和TestEntityManager
的教程,其中主要出处:
前者是切片测试,后者是EntityManager
的替代测试。
在其他教程中,我看到了许多 TestEntityManager
使用 persist
并随后在同一 @Test
中检索数据(针对 1 个或多个实体)的示例,因此插入是手动完成的。
主要问题:
- 那么什么时候有必要使用
TestEntityManager
类型(方法)而不是自定义 CrudRepository<T,ID>
方法来进行测试?
根本问题与 Spring Boot/Hibernate 或您的测试设置无关。
SQL 语句 SELECT COUNT(*) FROM Person
returns 单行单列包含计数行数:
$ SELECT COUNT(*) FROM Person;
COUNT(*)
----
4
这就是为什么您必须从本机或自定义查询的结果中调用 .getSingleResult()
的原因:
assertThat(personRepository.count())
.isEqualTo(4);
assertThat(testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
Spring Data JPA 在后台为 .count()
:
做完全相同的事情
public long count() {
return (Long)this.em.createQuery(this.getCountQueryString(), Long.class).getSingleResult();
}
您也可以直接为 @DataJpaTest
测试注入 EntityManager
而不需要 TestEntityManager
:
@DataJpaTest
class ApplicationTests {
@Autowired
private TestEntityManager testEntityManager;
@Autowired
private EntityManager entityManager;
@Autowired
private PersonRepository personRepository;
@Test
void contextLoads() {
assertThat(personRepository.count())
.isEqualTo(4);
//With TestEntityManager
assertThat(testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
//With EntityManager
assertThat(entityManager.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(entityManager.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
}
}
TestEntityManager
提供辅助方法,例如使用单行执行 persist/flush/find 操作(刷新内存中的持久性上下文并从数据库中读取相同的实体)。 TestEntityManager
永远不会 强制性 。
有一个 Spring 引导应用程序,使用 Spring 配置的数据 JPA 和 H2,它用于 sample/academic 目的。
存储库定义为:
public interface PersonaRepository extends CrudRepository<Persona, String> {
}
然后是下面的测试
@ActiveProfiles(profiles={"h2"})
@DataJpaTest
class PersonaRepositorySliceTests {
@Autowired
private PersonaRepository personaRepository;
@Autowired
private TestEntityManager testEntityManager;
@Test
void countTest() {
long count = personaRepository.count();
assertThat(count).isEqualTo(33);
count = testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Persona p")
.getResultList().size();
System.out.println("count: " + count);//prints 1
//assertThat(count).isEqualTo(33);//fails
count = testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM persona")
.getResultList().size();
System.out.println("count: " + count);//prints 1
assertThat(count).isEqualTo(33);//fails
}
}
long count = personaRepository.count();
assertThat(count).isEqualTo(33);
通过,因此检测到 @Entity
类,当然 schema-h2.sql
和 data-h2.sql
脚本也按预期执行。
现在的困惑是为什么
.createQuery("SELECT COUNT(*) FROM Persona p")
.createNativeQuery("SELECT COUNT(*) FROM persona")
有效 但 总是 returns 1,为什么不是 33 如何预期?
“似乎” TestEntityManager
在某种程度上 而不是 使用 [=15= 加载的数据] 文件。
二级问题:
- 这是预期的行为吗?
即使是,为什么返回1而不是0?还是强制性的额外配置?
看了一些关于@DataJpaTest
和TestEntityManager
的教程,其中主要出处:
前者是切片测试,后者是EntityManager
的替代测试。
在其他教程中,我看到了许多 TestEntityManager
使用 persist
并随后在同一 @Test
中检索数据(针对 1 个或多个实体)的示例,因此插入是手动完成的。
主要问题:
- 那么什么时候有必要使用
TestEntityManager
类型(方法)而不是自定义CrudRepository<T,ID>
方法来进行测试?
根本问题与 Spring Boot/Hibernate 或您的测试设置无关。
SQL 语句 SELECT COUNT(*) FROM Person
returns 单行单列包含计数行数:
$ SELECT COUNT(*) FROM Person;
COUNT(*)
----
4
这就是为什么您必须从本机或自定义查询的结果中调用 .getSingleResult()
的原因:
assertThat(personRepository.count())
.isEqualTo(4);
assertThat(testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
Spring Data JPA 在后台为 .count()
:
public long count() {
return (Long)this.em.createQuery(this.getCountQueryString(), Long.class).getSingleResult();
}
您也可以直接为 @DataJpaTest
测试注入 EntityManager
而不需要 TestEntityManager
:
@DataJpaTest
class ApplicationTests {
@Autowired
private TestEntityManager testEntityManager;
@Autowired
private EntityManager entityManager;
@Autowired
private PersonRepository personRepository;
@Test
void contextLoads() {
assertThat(personRepository.count())
.isEqualTo(4);
//With TestEntityManager
assertThat(testEntityManager.getEntityManager()
.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(testEntityManager.getEntityManager()
.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
//With EntityManager
assertThat(entityManager.createQuery("SELECT COUNT(*) FROM Person p", Long.class)
.getSingleResult())
.isEqualTo(4L);
assertThat(entityManager.createNativeQuery("SELECT COUNT(*) FROM Person")
.getSingleResult())
.isEqualTo(BigInteger.valueOf(4));
}
}
TestEntityManager
提供辅助方法,例如使用单行执行 persist/flush/find 操作(刷新内存中的持久性上下文并从数据库中读取相同的实体)。 TestEntityManager
永远不会 强制性 。