首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在内存数据库中用EntityManager测试H2查询

如何在内存数据库中用EntityManager测试H2查询
EN

Stack Overflow用户
提问于 2021-12-22 14:55:34
回答 1查看 454关注 0票数 0

我有一个Spring项目,我想测试一些查询。我希望插入一组预定义的数据,并执行Repository查询,以检查所需的结果。

为此,我使用内存中的H2 DB,问题(我认为)并不存在,与DB相关的一切都是正常的。主要问题是,我无法正确地模拟存储库中的EntityManager字段,而且查询始终为null。

我的存储库如下:

代码语言:javascript
复制
@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"));
    }

}

在测试之外执行时,它工作得很好,但是尝试运行这个测试文件会引发一个错误:

代码语言:javascript
复制
@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),但我不想那样,我在内存DB中有数据,所以我想执行查询并获得结果。

因此,我认为现在的主要问题是如何在存储库类中正确地模拟EntityManager对象。

提前谢谢。

编辑:

我一直在关注此链接,就像另一个这样的问题:它只是在嘲弄JpaRepository

我使用了这个代码:

代码语言:javascript
复制
@Test
public void it_should_works() {
    Result r = repository.findAll();
    assertNotNull(r);
}

并且工作得很好,但是使用我自己的查询时出错了:

代码语言:javascript
复制
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添加到存储库的问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-22 15:41:21

由于您使用内存中的h2数据库来运行测试,并且您希望在测试中实际使用该数据库,所以您不应该真的在模仿任何东西。

您的模拟不起作用,因为MyRepositoryImpl通常是由Spring初始化的,而且这个过程比插入EntityManager要复杂得多。

我认为你想做的事情更像这里所描述的,https://www.baeldung.com/spring-testing-separate-data-source

因此,您将有一个src/test/resources/application.properties文件,该文件覆盖数据源属性。然后,您只需像普通一样将您的存储库放到测试类中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70450960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档