All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.internal.injection.InjectionState Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains APIs for the creation of the objects to be tested, for mocking dependencies, and for faking external APIs; JUnit (4 & 5) and TestNG test runners are supported. It also contains an advanced code coverage tool.

The newest version!
/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.injection;

import static mockit.internal.injection.InjectionPoint.getQualifiedName;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import mockit.internal.reflection.FieldReflection;
import mockit.internal.reflection.GenericTypeReflection;

/**
 * Holds state used throughout the injection process while it's in progress for a given set of tested objects.
 */
public final class InjectionState {
    @NonNull
    private static final Map globalObjects = new ConcurrentHashMap<>(2);

    @NonNull
    private final Map testedObjects;
    @NonNull
    private final Map instantiatedDependencies;
    @NonNull
    public final InjectionProviders injectionProviders;
    @NonNull
    public final LifecycleMethods lifecycleMethods;
    @NonNull
    final InterfaceResolution interfaceResolution;
    @Nullable
    private BeanExporter beanExporter;
    private Object currentTestClassInstance;

    InjectionState() {
        testedObjects = new LinkedHashMap<>();
        instantiatedDependencies = new LinkedHashMap<>();
        lifecycleMethods = new LifecycleMethods();
        injectionProviders = new InjectionProviders(lifecycleMethods);
        interfaceResolution = new InterfaceResolution();
    }

    void setInjectables(@NonNull Object testClassInstance, @NonNull List injectables) {
        currentTestClassInstance = testClassInstance;
        injectionProviders.setInjectables(injectables);
        lifecycleMethods.getServletConfigForInitMethodsIfAny(injectables, testClassInstance);
    }

    void addInjectables(@NonNull Object testClassInstance,
            @NonNull List injectablesToAdd) {
        currentTestClassInstance = testClassInstance;
        List injectables = injectionProviders.addInjectables(injectablesToAdd);
        lifecycleMethods.getServletConfigForInitMethodsIfAny(injectables, testClassInstance);
    }

    Object getCurrentTestClassInstance() {
        return currentTestClassInstance;
    }

    @Nullable
    public Object getValueToInject(@NonNull InjectionProvider injectionProvider) {
        return injectionProviders.getValueToInject(injectionProvider, currentTestClassInstance);
    }

    void saveTestedObject(@NonNull InjectionPoint key, @NonNull Object testedObject, boolean global) {
        Map objects = global ? globalObjects : testedObjects;
        objects.put(key, testedObject);
    }

    @Nullable
    Object getTestedInstance(@NonNull InjectionPoint injectionPoint, boolean global) {
        Object testedInstance = instantiatedDependencies.isEmpty() ? null
                : findPreviouslyInstantiatedDependency(injectionPoint);

        if (testedInstance == null) {
            testedInstance = testedObjects.isEmpty() ? null : getValueFromExistingTestedObject(injectionPoint);
        }

        if (testedInstance == null && global) {
            testedInstance = globalObjects.get(injectionPoint);
        }

        return testedInstance;
    }

    @Nullable
    private Object findPreviouslyInstantiatedDependency(@NonNull InjectionPoint injectionPoint) {
        Object dependency = instantiatedDependencies.get(injectionPoint);

        if (dependency == null) {
            InjectionPoint injectionPointWithTypeOnly = new InjectionPoint(injectionPoint.type);
            dependency = instantiatedDependencies.get(injectionPointWithTypeOnly);

            if (dependency == null) {
                dependency = findMatchingObject(instantiatedDependencies, null, injectionPointWithTypeOnly);
            }
        }

        return dependency;
    }

    @Nullable
    private Object getValueFromExistingTestedObject(@NonNull InjectionPoint injectionPoint) {
        for (Object testedObject : testedObjects.values()) {
            Object fieldValue = getValueFromFieldOfEquivalentTypeAndName(injectionPoint, testedObject);

            if (fieldValue != null) {
                return fieldValue;
            }
        }

        return null;
    }

    @Nullable
    private static Object getValueFromFieldOfEquivalentTypeAndName(@NonNull InjectionPoint injectionPoint,
            @NonNull Object testedObject) {
        for (Field internalField : testedObject.getClass().getDeclaredFields()) {
            Type fieldType = internalField.getGenericType();
            String qualifiedName = getQualifiedName(internalField.getDeclaredAnnotations());
            boolean qualified = qualifiedName != null;
            String fieldName = qualified ? qualifiedName : internalField.getName();
            InjectionPoint internalInjectionPoint = new InjectionPoint(fieldType, fieldName, qualified);

            if (internalInjectionPoint.equals(injectionPoint)) {
                return FieldReflection.getFieldValue(internalField, testedObject);
            }
        }

        return null;
    }

    @Nullable
    @SuppressWarnings("unchecked")
    public static  D getGlobalDependency(@NonNull InjectionPoint key) {
        return (D) globalObjects.get(key);
    }

    @Nullable
    public Object getTestedValue(@NonNull TestedClass testedClass, @NonNull InjectionPoint injectionPoint) {
        Object testedValue = testedObjects.get(injectionPoint);

        if (testedValue == null) {
            testedValue = findMatchingObject(testedObjects, testedClass, injectionPoint);
        }

        return testedValue;
    }

    @Nullable
    public Object getInstantiatedDependency(@Nullable TestedClass testedClass, @NonNull InjectionPoint dependencyKey) {
        Object dependency = testedObjects.get(dependencyKey);

        if (dependency == null) {
            dependency = findMatchingObject(testedObjects, testedClass, dependencyKey);

            if (dependency == null) {
                dependency = instantiatedDependencies.get(dependencyKey);

                if (dependency == null) {
                    dependency = findMatchingObject(instantiatedDependencies, testedClass, dependencyKey);

                    if (dependency == null) {
                        dependency = findMatchingObject(globalObjects, testedClass, dependencyKey);
                    }
                }
            }
        }

        return dependency;
    }

    @Nullable
    private static Object findMatchingObject(@NonNull Map availableObjects,
            @Nullable TestedClass testedClass, @NonNull InjectionPoint injectionPoint) {
        if (availableObjects.isEmpty()) {
            return null;
        }

        GenericTypeReflection reflection = testedClass == null ? null : testedClass.reflection;
        Type dependencyType = injectionPoint.type;
        Object found = null;

        for (Entry injectionPointAndObject : availableObjects.entrySet()) {
            InjectionPoint dependencyIP = injectionPointAndObject.getKey();
            Object dependencyObject = injectionPointAndObject.getValue();

            if (injectionPoint.equals(dependencyIP)) {
                return dependencyObject;
            }

            if (reflection != null) {
                if (!reflection.areMatchingTypes(dependencyType, dependencyIP.type)) {
                    continue;
                }
                found = dependencyObject;
            }

            if (injectionPoint.hasSameName(dependencyIP)) {
                return dependencyObject;
            }
        }

        return injectionPoint.qualified ? null : found;
    }

    public void saveInstantiatedDependency(@NonNull InjectionPoint dependencyKey, @NonNull Object dependency) {
        instantiatedDependencies.put(dependencyKey, dependency);
    }

    public static void saveGlobalDependency(@NonNull InjectionPoint dependencyKey, @NonNull Object dependency) {
        globalObjects.put(dependencyKey, dependency);
    }

    void clearTestedObjectsAndInstantiatedDependencies() {
        testedObjects.clear();
        instantiatedDependencies.clear();
    }

    @NonNull
    BeanExporter getBeanExporter() {
        if (beanExporter == null) {
            beanExporter = new BeanExporter(this);
        }

        return beanExporter;
    }

    @Nullable
    public Class resolveInterface(@NonNull Class anInterface) {
        return interfaceResolution.resolveInterface(anInterface, currentTestClassInstance);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy