use of org.spockframework.mock.CannotCreateMockException in project spock by spockframework.
the class DefaultMethodInvoker method respond.
public Object respond(IMockInvocation invocation) {
// This implementation uses classes from the java.lang.invoke package in order to invoke a default method.
// Without exception handling, the implementation is analogous to the following code:
// final Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
// field.setAccessible(true);
// final MethodHandles.Lookup implLookup = (MethodHandles.Lookup) field.get(null);
// return implLookup.unreflectSpecial(method, method.getDeclaringClass()).bindTo(target).invokeWithArguments((Object)arguments);
// The java.lang.invoke package is only available since Java 7. In order to preserve the compatibility of spock-core
// with older versions of Java, we rewrite the above code using reflection.
Object boundHandle = null;
Method invokeWithArgumentsMethod = null;
try {
// Get the private field Lookup.IMPL_LOOKUP, which is maximally privileged
Class<?> lookupClass = Class.forName("java.lang.invoke.MethodHandles$Lookup");
final Field field = lookupClass.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
Object implLookup = field.get(null);
// Get a method handle for the default method
Method unreflectSpecialMethod = lookupClass.getMethod("unreflectSpecial", Method.class, Class.class);
Object specialHandle = unreflectSpecialMethod.invoke(implLookup, method, method.getDeclaringClass());
// Get a bound handle that prepends the target to the original arguments
Method bindToMethod = specialHandle.getClass().getMethod("bindTo", Object.class);
boundHandle = bindToMethod.invoke(specialHandle, target);
// Get the method MethodHandle.invokeWithArguments(Object...)
invokeWithArgumentsMethod = boundHandle.getClass().getMethod("invokeWithArguments", Object[].class);
} catch (Exception e) {
throw new CannotCreateMockException(target.getClass(), "Failed to invoke default method '" + method.getName() + "'", e);
}
// Call boundHandle.invokeWithArguments(arguments), sneaky throwing possible exceptions
Object result = ReflectionUtil.invokeMethod(boundHandle, invokeWithArgumentsMethod, (Object) arguments);
return result;
}
use of org.spockframework.mock.CannotCreateMockException in project spock by spockframework.
the class GroovyMockFactory method create.
public Object create(IMockConfiguration configuration, Specification specification) throws CannotCreateMockException {
final MetaClass oldMetaClass = GroovyRuntimeUtil.getMetaClass(configuration.getType());
GroovyMockMetaClass newMetaClass = new GroovyMockMetaClass(configuration, specification, oldMetaClass);
final Class<?> type = configuration.getType();
if (configuration.isGlobal()) {
if (type.isInterface()) {
throw new CannotCreateMockException(type, ". Global mocking is only possible for classes, but not for interfaces.");
}
GroovyRuntimeUtil.setMetaClass(type, newMetaClass);
specification.getSpecificationContext().getCurrentIteration().addCleanup(new Runnable() {
public void run() {
GroovyRuntimeUtil.setMetaClass(type, oldMetaClass);
}
});
return MockInstantiator.instantiate(type, type, configuration.getConstructorArgs(), configuration.isUseObjenesis());
}
if (isFinalClass(type)) {
final Object instance = MockInstantiator.instantiate(type, type, configuration.getConstructorArgs(), configuration.isUseObjenesis());
GroovyRuntimeUtil.setMetaClass(instance, newMetaClass);
return instance;
}
IProxyBasedMockInterceptor mockInterceptor = new GroovyMockInterceptor(configuration, specification, newMetaClass);
return ProxyBasedMockFactory.INSTANCE.create(type, Collections.<Class<?>>singletonList(GroovyObject.class), configuration.getConstructorArgs(), mockInterceptor, specification.getClass().getClassLoader(), configuration.isUseObjenesis());
}
Aggregations