Skip to content

Instantly share code, notes, and snippets.

@swankjesse
Created March 2, 2013 14:14
Show Gist options
  • Save swankjesse/5071165 to your computer and use it in GitHub Desktop.
Save swankjesse/5071165 to your computer and use it in GitHub Desktop.
Test that shows that how package-private methods are dispatched depends on class loading.
package org.mockitousage.packageprotected;
import org.junit.Test;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import org.mockitoutil.ClassLoaderBuilder;
import org.mockitoutil.TestBase;
public class MockingAndClassLoadersTest extends TestBase {
public static class ProductionClass {
String packageProtected() {
return "package protected";
}
public String callPackageProtected() {
return packageProtected();
}
}
public static class TestClass implements Runnable {
public void run() {
ProductionClass c = spy(new ProductionClass());
assertEquals("package protected", c.callPackageProtected());
verify(c).callPackageProtected();
verify(c).packageProtected(); // Fails if multiple class loaders are involved!
verifyNoMoreInteractions(c);
}
}
/**
* This confirms that package-protected methods are mockable when everything
* is in the same class loader.
*/
@Test
public void packageProtectedWithoutClassLoaders() throws Exception {
// Contrast with the test above by loading everything in the same loader.
Runnable r = new TestClass();
r.run();
}
/**
* This test creates a separate class loader, which causes Mockito to use
* its SearchingClassLoader. Once SearchingClassLoader is involved, package
* protected methods are not mockable! So the package-protected call fails
* to verify.
*
* <p>This uses AOSP's ClassLoaderBuilder, but any 2nd class loader should
* be sufficient.
*/
@Test
public void packageProtectedAndClassLoaders() throws Exception {
String testClassName = MockingAndClassLoadersTest.class.getName() + "$TestClass";
// Run test code in a separate class loader.
ClassLoader loader = new ClassLoaderBuilder()
.withPrivateCopy("org.mockito.")
.withPrivateCopy("org.mockitousage.")
.build();
Class<?> testClass = loader.loadClass(testClassName);
Runnable r = (Runnable) testClass.newInstance();
r.run();
}
}
@swankjesse
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment