public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Class<?>... ancillaryTypes) { Class<Factory> proxyClass = null; Object proxyInstance = null; try { setConstructorsAccessible(mockedType, true); proxyClass = createProxyClass(mockedType, ancillaryTypes); proxyInstance = createProxy(proxyClass, interceptor); return mockedType.cast(proxyInstance); } catch (ClassCastException cce) { throw new MockitoException(join( "ClassCastException occurred while creating the mockito proxy :", " class to mock : " + describeClass(mockedType), " created class : " + describeClass(proxyClass), " proxy instance class : " + describeClass(proxyInstance), " instance creation by : " + instantiator.getClass().getSimpleName(), "", "You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)" ), cce); } finally { setConstructorsAccessible(mockedType, false); } }
/** * {@inheritDoc} */ public Class<?> getUnproxiedType(Class<?> type) { Class<?> currentType = type; while (isProxy(currentType)) { for (Class<?> i : currentType.getInterfaces()) { if (!i.getName().equals(Factory.class.getName())) { return i; } } currentType = currentType.getSuperclass(); } return currentType; }
public MockHandler getHandler(Object mock) { if (!(mock instanceof Factory)) { return null; } Factory factory = (Factory) mock; Callback callback = factory.getCallback(0); if (!(callback instanceof MethodInterceptorFilter)) { return null; } return ((MethodInterceptorFilter) callback).getHandler(); }
private Object createProxy(Class<Factory> proxyClass, final MethodInterceptor interceptor) { Factory proxy; try { proxy = instantiator.newInstance(proxyClass); } catch (InstantiationException e) { throw new MockitoException("Unable to create mock instance of type '" + proxyClass.getSuperclass().getSimpleName() + "'", e); } proxy.setCallbacks(new Callback[] {interceptor, SerializableNoOp.SERIALIZABLE_INSTANCE }); return proxy; }
@Test public void shouldMocksHaveDifferentInterceptors() throws Exception { SomeClass mockOne = imposterizer.imposterise(new MethodInterceptorStub(), SomeClass.class); SomeClass mockTwo = imposterizer.imposterise(new MethodInterceptorStub(), SomeClass.class); Factory cglibFactoryOne = (Factory) mockOne; Factory cglibFactoryTwo = (Factory) mockTwo; assertNotSame(cglibFactoryOne.getCallback(0), cglibFactoryTwo.getCallback(0)); }
@Test public void shouldMocksHaveDifferentInterceptors() throws Exception { SomeClass mockOne = ClassImposterizer.INSTANCE.imposterise(new MethodInterceptorStub(), SomeClass.class); SomeClass mockTwo = ClassImposterizer.INSTANCE.imposterise(new MethodInterceptorStub(), SomeClass.class); Factory cglibFactoryOne = (Factory) mockOne; Factory cglibFactoryTwo = (Factory) mockTwo; assertNotSame(cglibFactoryOne.getCallback(0), cglibFactoryTwo.getCallback(0)); }
public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) { ((Factory) mock).setCallback(0, new MethodInterceptorFilter(cast(newHandler), settings)); }
public Class<Factory> createProxyClass(Class<?> mockedType, Class<?>... interfaces) { if (mockedType == Object.class) { mockedType = ClassWithSuperclassToWorkAroundCglibBug.class; } Enhancer enhancer = new Enhancer() { @Override @SuppressWarnings("unchecked") protected void filterConstructors(Class sc, List constructors) { // Don't filter } }; Class<?>[] allMockedTypes = prepend(mockedType, interfaces); enhancer.setClassLoader(SearchingClassLoader.combineLoadersOf(allMockedTypes)); enhancer.setUseFactory(true); if (mockedType.isInterface()) { enhancer.setSuperclass(Object.class); enhancer.setInterfaces(allMockedTypes); } else { enhancer.setSuperclass(mockedType); enhancer.setInterfaces(interfaces); } enhancer.setCallbackTypes(new Class[]{MethodInterceptor.class, NoOp.class}); enhancer.setCallbackFilter(IGNORE_BRIDGE_METHODS); if (mockedType.getSigners() != null) { enhancer.setNamingPolicy(NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES); } else { enhancer.setNamingPolicy(MockitoNamingPolicy.INSTANCE); } enhancer.setSerialVersionUID(42L); try { return enhancer.createClass(); } catch (CodeGenerationException e) { if (Modifier.isPrivate(mockedType.getModifiers())) { throw new MockitoException("\n" + "Mockito cannot mock this class: " + mockedType + ".\n" + "Most likely it is a private class that is not visible by Mockito"); } throw new MockitoException("\n" + "Mockito cannot mock this class: " + mockedType + "\n" + "Mockito can only mock visible & non-final classes." + "\n" + "If you're not sure why you're getting this error, please report to the mailing list.", e); } }