使用createquery()、参数和executeupdate()模拟hibernate entitymanager

to94eoyn  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(683)

我是java单元测试的新手;我有一个使用hibernate与mysql数据库交互的应用程序。
我有很多用 createQuery() 方法,也带有参数,如以下参数:

return this.entityManager.createQuery("from MyEntity m where param  = :param", MyEntity.class)
    .setParameter("param", param)
    .getSingleResult();

我想避免嘲笑所有后续的电话会议 entityManager 对象,因为有时我会使用5个以上的参数进行查询,而模拟每个调用似乎不是那么方便。
同样的概念也可以应用于生成器对象。
编辑1
我添加了一个具体的例子来说明我所使用的方法(考虑到这不是一个管理异常的好方法,但不幸的是它通常是安静的):

public class MyService {
private EntityManager entityManager;

public MyEntity find(String field ) {
        try{
            return this.entityManager.createQuery("from MyEntity  c where c.field = :field ", MyEntity .class)
                    .setParameter("field ", field )
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        } catch (NonUniqueResultException e) {
            logger.error("find", e);
            return null;
        }
    }
}

在本例中,给定 entityManager 我有不同的分支需要测试。然后我必须模拟这个调用的答案来测试这个方法的所有行。

我发现了什么

我发现的是:

@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private EntityManager entityManager;

一切如期。我可以模仿所有的电话链。但是
引用mockito.returns\u deep\u stubs的javadoc:
警告:对于常规的干净代码,应该很少需要此功能!留给遗留代码。mocking a mock返回一个mock,返回一个mock,(…),返回一些有意义的提示,表示违反了demeter定律,或者模仿了一个值对象(一个众所周知的反模式)。
如果上一点还不够,下一点,后面的几行,显然设置了很大的限制:
当链中包含的任何返回类型的方法都无法模拟时(例如:是原语或final类),此功能将不起作用。这是因为java类型的系统。
第二点意味着如果我试图用这种方式来模拟 executeUpdate() ,返回 int ,它引发了一个异常。

when(entityManager.createQuery(anyString())
                .setParameter(eq("param"), anyString())
                .executeUpdate())
.thenReturn(1);

这样我就不能测试和 entityManager .

问题

我该如何嘲笑电话 entityManager ? 在我看来,我不可能一个一个地嘲笑每一种方法。
用错了吗 Answers.RETURNS_DEEP_STUBS ? 如果没有,我如何处理第二个例子?

tct7dpnv

tct7dpnv1#

不要模仿jpaapi,只要用适当的测试数据编写集成测试,并对实际数据执行真正的查询,看看是否一切正常。像testcontainers这样的项目使它非常容易启动。

相关问题