• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.74
/main/src/main/java/mockit/internal/injection/Injector.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.internal.injection;
7

8
import static java.lang.reflect.Modifier.isFinal;
9
import static java.lang.reflect.Modifier.isStatic;
10
import static java.lang.reflect.Modifier.isVolatile;
11
import static java.util.regex.Pattern.compile;
12

13
import static mockit.internal.injection.InjectionPoint.JAKARTA_PERSISTENCE_UNIT_CLASS;
14
import static mockit.internal.injection.InjectionPoint.JAVAX_PERSISTENCE_UNIT_CLASS;
15
import static mockit.internal.injection.InjectionPoint.convertToLegalJavaIdentifierIfNeeded;
16
import static mockit.internal.injection.InjectionPoint.getQualifiedName;
17
import static mockit.internal.injection.InjectionPoint.isJakartaServlet;
18
import static mockit.internal.injection.InjectionPoint.isJavaxServlet;
19
import static mockit.internal.injection.InjectionPoint.kindOfInjectionPoint;
20
import static mockit.internal.injection.InjectionPoint.wrapInProviderIfNeeded;
21
import static mockit.internal.injection.InjectionProvider.NULL;
22

23
import edu.umd.cs.findbugs.annotations.NonNull;
24
import edu.umd.cs.findbugs.annotations.Nullable;
25

26
import java.lang.reflect.Field;
27
import java.lang.reflect.Type;
28
import java.lang.reflect.TypeVariable;
29
import java.util.ArrayList;
30
import java.util.List;
31
import java.util.regex.Pattern;
32

33
import mockit.internal.injection.InjectionPoint.KindOfInjectionPoint;
34
import mockit.internal.injection.field.FieldToInject;
35
import mockit.internal.injection.full.FullInjection;
36
import mockit.internal.reflection.FieldReflection;
37
import mockit.internal.util.DefaultValues;
38

39
public class Injector {
40
    private static final Pattern TYPE_NAME = compile("class |interface |java\\.lang\\.");
1✔
41

42
    @NonNull
43
    protected final InjectionState injectionState;
44
    @Nullable
45
    protected final FullInjection fullInjection;
46

47
    protected Injector(@NonNull InjectionState state, @Nullable FullInjection fullInjection) {
1✔
48
        injectionState = state;
1✔
49
        this.fullInjection = fullInjection;
1✔
50
    }
1✔
51

52
    @NonNull
53
    static List<Field> findAllTargetInstanceFieldsInTestedClassHierarchy(@NonNull Class<?> actualTestedClass,
54
            @NonNull TestedClass testedClass) {
55
        List<Field> targetFields = new ArrayList<>();
1✔
56
        Class<?> classWithFields = actualTestedClass;
1✔
57

58
        do {
59
            addEligibleFields(targetFields, classWithFields);
1✔
60
            classWithFields = classWithFields.getSuperclass();
1✔
61
        } while (testedClass.isClassFromSameModuleOrSystemAsTestedClass(classWithFields)
1✔
62
                || isJakartaServlet(classWithFields) || isJavaxServlet(classWithFields));
1!
63

64
        return targetFields;
1✔
65
    }
66

67
    private static void addEligibleFields(@NonNull List<Field> targetFields, @NonNull Class<?> classWithFields) {
68
        Field[] fields = classWithFields.getDeclaredFields();
1✔
69

70
        for (Field field : fields) {
1✔
71
            if (isEligibleForInjection(field)) {
1✔
72
                targetFields.add(field);
1✔
73
            }
74
        }
75
    }
1✔
76

77
    private static boolean isEligibleForInjection(@NonNull Field field) {
78
        int modifiers = field.getModifiers();
1✔
79

80
        if (isFinal(modifiers)) {
1✔
81
            return false;
1✔
82
        }
83

84
        if (kindOfInjectionPoint(field) != KindOfInjectionPoint.NotAnnotated) {
1✔
85
            return true;
1✔
86
        }
87

88
        if (JAKARTA_PERSISTENCE_UNIT_CLASS != null
1!
89
                && field.getType().isAnnotationPresent(jakarta.persistence.Entity.class)) {
1✔
90
            return false;
1✔
91
        }
92

93
        if (JAVAX_PERSISTENCE_UNIT_CLASS != null
1!
94
                && field.getType().isAnnotationPresent(javax.persistence.Entity.class)) {
1!
95
            return false;
×
96
        }
97

98
        return !isStatic(modifiers) && !isVolatile(modifiers);
1✔
99
    }
100

101
    public final void fillOutDependenciesRecursively(@NonNull Object dependency, @NonNull TestedClass testedClass) {
102
        Class<?> dependencyClass = dependency.getClass();
1✔
103
        List<Field> targetFields = findAllTargetInstanceFieldsInTestedClassHierarchy(dependencyClass, testedClass);
1✔
104

105
        if (!targetFields.isEmpty()) {
1✔
106
            List<InjectionProvider> currentlyConsumedInjectables = injectionState.injectionProviders
1✔
107
                    .saveConsumedInjectionProviders();
1✔
108
            injectIntoEligibleFields(targetFields, dependency, testedClass);
1✔
109
            injectionState.injectionProviders.restoreConsumedInjectionProviders(currentlyConsumedInjectables);
1✔
110
        }
111
    }
1✔
112

113
    public final void injectIntoEligibleFields(@NonNull List<Field> targetFields, @NonNull Object testedObject,
114
            @NonNull TestedClass testedClass) {
115
        for (Field field : targetFields) {
1✔
116
            if (targetFieldWasNotAssignedByConstructor(testedObject, field)) {
1✔
117
                Object injectableValue = getValueForFieldIfAvailable(targetFields, testedClass, field);
1✔
118

119
                if (injectableValue != null && injectableValue != NULL) {
1✔
120
                    injectableValue = wrapInProviderIfNeeded(field.getGenericType(), injectableValue);
1✔
121
                    FieldReflection.setFieldValue(field, testedObject, injectableValue);
1✔
122
                }
123
            }
124
        }
1✔
125
    }
1✔
126

127
    private static boolean targetFieldWasNotAssignedByConstructor(@NonNull Object testedObject,
128
            @NonNull Field targetField) {
129
        if (kindOfInjectionPoint(targetField) != KindOfInjectionPoint.NotAnnotated) {
1✔
130
            return true;
1✔
131
        }
132

133
        Object fieldValue = FieldReflection.getFieldValue(targetField, testedObject);
1✔
134

135
        if (fieldValue == null) {
1✔
136
            return true;
1✔
137
        }
138

139
        Class<?> fieldType = targetField.getType();
1✔
140

141
        if (!fieldType.isPrimitive()) {
1✔
142
            return false;
1✔
143
        }
144

145
        Object defaultValue = DefaultValues.defaultValueForPrimitiveType(fieldType);
1✔
146

147
        return fieldValue.equals(defaultValue);
1✔
148
    }
149

150
    @Nullable
151
    private Object getValueForFieldIfAvailable(@NonNull List<Field> targetFields, @NonNull TestedClass testedClass,
152
            @NonNull Field targetField) {
153
        @Nullable
154
        String qualifiedFieldName = getQualifiedName(targetField.getDeclaredAnnotations());
1✔
155
        InjectionProvider injectable = findAvailableInjectableIfAny(targetFields, qualifiedFieldName, testedClass,
1✔
156
                targetField);
157

158
        if (injectable != null) {
1✔
159
            return injectionState.getValueToInject(injectable);
1✔
160
        }
161

162
        InjectionProvider fieldToInject = new FieldToInject(targetField);
1✔
163
        Type typeToInject = fieldToInject.getDeclaredType();
1✔
164
        InjectionPoint injectionPoint = new InjectionPoint(typeToInject, fieldToInject.getName(), qualifiedFieldName);
1✔
165
        TestedClass nextTestedClass = typeToInject instanceof TypeVariable<?> ? testedClass
1✔
166
                : new TestedClass(typeToInject, fieldToInject.getClassOfDeclaredType(), testedClass);
1✔
167
        Object testedValue = injectionState.getTestedValue(nextTestedClass, injectionPoint);
1✔
168

169
        if (testedValue != null) {
1✔
170
            return testedValue;
1✔
171
        }
172

173
        if (fullInjection != null) {
1✔
174
            Object newInstance = fullInjection.createOrReuseInstance(nextTestedClass, this, fieldToInject,
1✔
175
                    qualifiedFieldName);
176

177
            if (newInstance != null) {
1✔
178
                return newInstance;
1✔
179
            }
180
        }
181

182
        KindOfInjectionPoint kindOfInjectionPoint = kindOfInjectionPoint(targetField);
1✔
183
        throwExceptionIfUnableToInjectRequiredTargetField(kindOfInjectionPoint, targetField, qualifiedFieldName);
1✔
184
        return null;
1✔
185
    }
186

187
    @Nullable
188
    private InjectionProvider findAvailableInjectableIfAny(@NonNull List<Field> targetFields,
189
            @Nullable String qualifiedTargetFieldName, @NonNull TestedClass testedClass, @NonNull Field targetField) {
190
        KindOfInjectionPoint kindOfInjectionPoint = kindOfInjectionPoint(targetField);
1✔
191
        InjectionProviders injectionProviders = injectionState.injectionProviders;
1✔
192
        injectionProviders.setTypeOfInjectionPoint(targetField.getGenericType(), kindOfInjectionPoint);
1✔
193

194
        if (qualifiedTargetFieldName != null && !qualifiedTargetFieldName.isEmpty()) {
1!
195
            String injectableName = convertToLegalJavaIdentifierIfNeeded(qualifiedTargetFieldName);
1✔
196
            InjectionProvider matchingInjectable = injectionProviders.findInjectableByTypeAndName(injectableName,
1✔
197
                    testedClass);
198

199
            if (matchingInjectable != null) {
1✔
200
                return matchingInjectable;
1✔
201
            }
202
        }
203

204
        String targetFieldName = targetField.getName();
1✔
205

206
        if (withMultipleTargetFieldsOfSameType(targetFields, testedClass, targetField, injectionProviders)) {
1✔
207
            return injectionProviders.findInjectableByTypeAndName(targetFieldName, testedClass);
1✔
208
        }
209

210
        return injectionProviders.getProviderByTypeAndOptionallyName(targetFieldName, testedClass);
1✔
211
    }
212

213
    private static boolean withMultipleTargetFieldsOfSameType(@NonNull List<Field> targetFields,
214
            @NonNull TestedClass testedClass, @NonNull Field targetField,
215
            @NonNull InjectionProviders injectionProviders) {
216
        for (Field anotherTargetField : targetFields) {
1✔
217
            if (anotherTargetField != targetField && injectionProviders
1✔
218
                    .isAssignableToInjectionPoint(anotherTargetField.getGenericType(), testedClass)) {
1✔
219
                return true;
1✔
220
            }
221
        }
1✔
222

223
        return false;
1✔
224
    }
225

226
    private void throwExceptionIfUnableToInjectRequiredTargetField(@NonNull KindOfInjectionPoint kindOfInjectionPoint,
227
            @NonNull Field targetField, @Nullable String qualifiedFieldName) {
228
        if (kindOfInjectionPoint == KindOfInjectionPoint.Required) {
1✔
229
            Type fieldType = targetField.getGenericType();
1✔
230
            String fieldTypeName = fieldType.toString();
1✔
231
            fieldTypeName = TYPE_NAME.matcher(fieldTypeName).replaceAll("");
1✔
232
            String kindOfInjectable = "@Tested or @Injectable";
1✔
233

234
            if (fullInjection != null) {
1!
235
                if (targetField.getType().isInterface()) {
×
236
                    kindOfInjectable = "@Tested instance of an implementation class";
×
237
                } else {
238
                    kindOfInjectable = "@Tested object";
×
239
                }
240
            }
241

242
            throw new IllegalStateException("Missing " + kindOfInjectable + " for field " + fieldTypeName + ' '
1✔
243
                    + targetField.getName() + (qualifiedFieldName == null ? "" : " (\"" + qualifiedFieldName + "\")")
1✔
244
                    + " in " + targetField.getDeclaringClass().getSimpleName());
1✔
245
        }
246
    }
1✔
247
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc