【发布时间】:2022-01-23 18:58:24
【问题描述】:
我有一个 Spring Boot 项目,我想测试一些查询。我想插入一组预定义的数据并执行存储库查询以检查结果是否是所需的。
为此,我使用的是内存 H2 DB,但问题(我认为)不存在,与 DB 相关的一切都正常。主要问题是我无法正确模拟存储库中的EntityManager 字段,并且查询始终为空。
我的仓库是这样的:
@Repository
public class MyRepositoryImpl implements MyRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public Result runQuery() {
TypedQuery<Result> query = entityManager.createQuery(
"SELECT ...", Result.class);
return query.setParameter("...", "...") // here 'query' is always null
.setMaxResults(1)
.getResultStream()
.findFirst()
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Entity not found"));
}
}
在测试之外执行时效果很好,但是尝试运行此测试文件会引发错误:
@RunWith(SpringRunner.class)
public class MyRepositoryTest {
@Mock
EntityManager entityManager;
@InjectMocks
MyRepositoryImpl repository;
@Test
public void it_should_works() {
Result r = repository.runQuery();
assertNull(r);
}
}
存储库被模拟并且不为空,我可以调用该方法。但是在仓库内部,由于query字段为空,尝试执行时会抛出NullPointerException。
我在互联网上搜索了很多方法来测试界面内的JPARepository 和@Query,但不是EntityManager 查询。
我还找到了一些模拟查询结果的方法,比如when(runQuery()).thenReturn(result),但我不希望这样,我在内存数据库中有数据,所以我想执行查询并获取结果。
所以,现在,我认为的主要问题是如何在存储库类中正确地模拟 EntityManager 对象。
提前致谢。
编辑:
我已经关注 this link 并且就像另一个 SO 问题:这只是为了模拟 JpaRepository。
我用过这段代码:
@Test
public void it_should_works() {
Result r = repository.findAll();
assertNotNull(r);
}
而且效果很好,但是使用我自己的查询失败并出现错误:
org.springframework.orm.jpa.JpaSystemException: could not advance using next(); nested exception is org.hibernate.exception.GenericJDBCException: could not advance using next()
...
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: El objeto ya está cerrado
The object is already closed [90007-200]
所以问题是:它与我的数据库有关吗?为什么使用 JpaRepository 方法它可以工作,但我自己的查询却不行?
编辑:
解决了将@Transactional 添加到存储库的问题。
【问题讨论】:
标签: java spring-boot testing h2