Search in sources :

Example 1 with CannotCreateMockException

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;
}
Also used : Field(java.lang.reflect.Field) CannotCreateMockException(org.spockframework.mock.CannotCreateMockException) Method(java.lang.reflect.Method) CannotCreateMockException(org.spockframework.mock.CannotCreateMockException)

Example 2 with CannotCreateMockException

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());
}
Also used : MetaClass(groovy.lang.MetaClass) CannotCreateMockException(org.spockframework.mock.CannotCreateMockException) GroovyObject(groovy.lang.GroovyObject) GroovyObject(groovy.lang.GroovyObject)

Aggregations

CannotCreateMockException (org.spockframework.mock.CannotCreateMockException)2 GroovyObject (groovy.lang.GroovyObject)1 MetaClass (groovy.lang.MetaClass)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1