Package org.mockito.internal.creation

Source Code of org.mockito.internal.creation.MockFactory

/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.creation;

import java.lang.reflect.Modifier;
import java.util.List;

import net.sf.cglib.core.CollectionUtils;
import net.sf.cglib.core.VisibilityPredicate;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;

import org.mockito.exceptions.Reporter;

/**
* Factory generating a mock for a class.
*/
public class MockFactory<T> {

    @SuppressWarnings("unchecked")
    public T createMock(Class<T> toMock, final MethodInterceptorFilter filter) {
        validateClass(toMock);
        Enhancer enhancer = createEnhancer(toMock);
        enhancer.setCallbackType(filter.getClass());

        Class mockClass = enhancer.createClass();
        Enhancer.registerCallbacks(mockClass, new Callback[] { filter });

        Factory mock = createMock(mockClass);

        filter.setMock(mock);
        return (T) mock;
    }

    private void validateClass(Class<T> toMock) {
        if (Modifier.isFinal(toMock.getModifiers())) {
            new Reporter().cannotMockFinalClass(toMock);
        }
    }

    private Enhancer createEnhancer(Class<T> toMock) {
        Enhancer enhancer = new Enhancer() {
            @SuppressWarnings("unchecked")
            //Filter all private constructors but do not check that there are some left
            protected void filterConstructors(Class sc, List constructors) {
                CollectionUtils.filter(constructors, new VisibilityPredicate(
                        sc, true));
            }
        };

        if (toMock.isInterface()) {
            enhancer.setInterfaces(new Class[] { toMock });
        } else {
            enhancer.setSuperclass(toMock);
        }
        return enhancer;
    }

    private Factory createMock(Class<?> mockClass) {
        Factory mock;
        try {
            mock = (Factory) ObjenesisClassInstantiator.newInstance(mockClass);
        } catch (InstantiationException e) {
            throw new RuntimeException("Fail to instantiate mock for " + mockClass
                    + " on " + System.getProperty("java.vm.vendor") + " JVM");
        }

        // This call is required. Cglib has some "magic code" making sure a
        // callback is used by only one instance of a given class. So only the
        // instance created right after registering the callback will get it.
        // However, this is done in the construtor which I'm bypassing to
        // allow class instantiation without calling a constructor.
        // Fortunatly, the "magic code" is also called in getCallback which is
        // why I'm calling it here mock.getCallback(0);

        mock.getCallback(0);
        return mock;
    }
}
TOP

Related Classes of org.mockito.internal.creation.MockFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.