【问题标题】:Mockito argument matcher and hibernate lazyinitializationMockito 参数匹配器和休眠延迟初始化
【发布时间】:2019-08-06 09:47:32
【问题描述】:

我创建了以下捕获器:

public class CompanyOwnerMatcher extends ArgumentMatcher<CompanyOwner> {

    private String uuid;

    CompanyOwnerMatcher(String uuid) {
        this.uuid = uuid;
    }

    @Override
    public boolean matches(Object arg) {
        if (!(arg instanceof CompanyOwner)) return false;
        CompanyOwner owner = (CompanyOwner) arg;
        return Objects.equals(uuid, owner.getUuid());
    }
}

我在这段代码中遇到异常:

Mockito.verify(payInApi).submit(eq(1L), argThat(new CompanyOwnerMatcher(expectedOwnerUuid)));

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:148)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)

CompanyOwner 由休眠管理。这很奇怪,但是在我捕捉到 CompanyOwner 之后,我无法获取任何字段值,因为我得到了 LazyInitializationException,即使在未标记为 Lazy 的字段上也是如此。

对于这个问题的任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 向我们展示测试类和方法

标签: java junit mockito spring-test


【解决方案1】:

我相信,Hibernate 创建了某种CompanyOwner 的代理。 然后它真的取决于代码,很可能当你调用匹配器时,对象已经从 Hibernate Session 中分离出来。 在这种情况下,当您尝试访问您提到的字段时,您将收到 LazyInitializationException。

真的不可能从提供的代码中理解为什么休眠决定用代理包装对象,我只能建议在matches方法中放置一个断点以确保这确实是代理但是你'必须弄清楚制作这个代理的原因。

如果您发现在这种情况下确实必须执行代理,那么最好的办法可能是将对象“重新附加”到会话。异常应该会消失,但是在这种情况下您可能会看到 hibernate 发出一个 DB 请求。

您可能还对This thread感兴趣

【讨论】:

  • Afaik 使用代理,直到有人通过调用所述对象的方法实际从它请求数据。此时会触发 db 查询以检索数据。如果代理/实体已经分离,您最终会出现该错误。
  • 从设计的角度来看,这可能表明您不应将实体传递到数据库层之外,最好使用POJO's。这样做的好处是您的应用程序的其余部分不关心您的数据库设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
  • 2015-05-19
  • 2013-09-14
  • 2014-01-10
相关资源
最近更新 更多