'Mockito argument matcher and hibernate lazyinitialization

I've created the following captor:

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());
    }
}

I get an exception in this code:

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 is managed by hibernate. It's weird, but after I catch a CompanyOwner, I can't get any field values on it because I get LazyInitializationException, even on fields that are not marked as Lazy.

Would appreciate any help with regards to this problem.

Thanks!



Solution 1:[1]

I believe, Hibernate creates some kind of proxy of CompanyOwner. Then it really depends on the code, the chances are that by the time you call the matcher the object is already detached from Hibernate Session. In this case, you'll get the LazyInitializationException when you try to access fields like you've mentioned.

Its really impossible to understand out of the supplied code snipped why exactly the hibernate decides to wrap the object with proxy, I can only suggest to place a breakpoint in matches method to make sure that this is proxy indeed but then you'll have to figure out the reason for making this proxy.

If you see that proxy is indeed must be done in this case, probably the best would be "re-attaching" the object to the session. The exception should disappear however you'll probably see that hibernate issues a DB request in this case.

You might also be interested in This thread

Solution 2:[2]

if your object looks like it is proxied by hibernate (not yet fetched from DB because the entity is marked as LAZY), you can find out and force unproxy like this:

public <T extends BaseObject> T unproxy(final T arg) {
        if (arg instanceof HibernateProxy) {
            return (T) Hibernate.unproxy(arg);
        }
        return arg;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mark Bramnik
Solution 2 mojjj