mockito / mockito

Most popular Mocking framework for unit tests written in Java
http://mockito.org
MIT License
14.92k stars 2.57k forks source link

Mockito keeps references to disposed class loaders in the #320

Open jedvardsson opened 9 years ago

jedvardsson commented 9 years ago

In our projects we have tests that fire up embedded Tomcats + Spring web application context. In the Spring application context we create beans using Mockito mocks.

The problem is that Mockito mock proxy classes gets a class loader based not only on the class being mocked but also the current threads class loader. In our case the current thread is a thread owned by tomcat.

This is not good because in our tests we create and dispose several tomcat instances, meaning that there are mock classes in the Mockito class cache with references to old (disposed) Tomcat class loaders.

In our case Spring logs a debug exception when trying to get bean info from the mock class. This in turn triggers a call to the class loader which will then hit the disposed Tomcat class loader.

Large test suites may run out of memory since class loaders are not released.

Workarounds are either to create mocks in the main application thread or to disable class caching by implementing org.mockito.configuration.configuration.MockitoConfiguration.

bric3 commented 8 years ago

That is correct, mockito may run in different configuration, hence there's a strategy to search for the best classloader. While the main target is unit test mockito is used in context like yours. I don't think we can fix the issue in your context without breaking stuff for everyone else. However documenting the issue and the workaround in the wiki is possible.

bric3 commented 8 years ago

Also you should always mention version, there maybe subtle changes between versions of either spring, tomcat, mockito, or maven plugins

TimvdLippe commented 8 years ago

@bric3 Do we require any action here or has this been resolved in Mockito 2?

bric3 commented 8 years ago

Not resolved, we could use some time to document the classloader mechanism. However it has changed with the bytebuddy mockmaker. I believe the case reported is with mockito 1.x.

raphw commented 8 years ago

We are still referencing the thread-context class loader. There was an issue saying this was required for Eclipse but I do not really see why we would need that. Can we remove this reference?

bric3 commented 8 years ago

I meant mockito 2 don't use anymore SearchingClassloader, instead we use the nifty bytebuddy classloader builder. I don't really remember how SearchingClassloader worked, but here's the new code (2.2.8)

new MultipleParentClassLoader.Builder()
   .append(features.mockedType)
   .append(features.interfaces)
   .append(currentThread().getContextClassLoader())
   .append(MockAccess.class,
           DispatcherDefaultingToRealMethod.class)
   .append(MockMethodInterceptor.class,
           MockMethodInterceptor.ForHashCode.class,
           MockMethodInterceptor.ForEquals.class).build()

Good question, I don't know! I'm not an Eclipse user, the change may be incompatible for older eclipse version though (if not other tools that had/have the same behaviour).