• 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

94.44
/main/src/main/java/mockit/internal/expectations/mocking/MockedType.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.expectations.mocking;
7

8
import static java.lang.reflect.Modifier.isFinal;
9

10
import edu.umd.cs.findbugs.annotations.NonNull;
11
import edu.umd.cs.findbugs.annotations.Nullable;
12

13
import java.lang.annotation.Annotation;
14
import java.lang.reflect.Field;
15
import java.lang.reflect.ParameterizedType;
16
import java.lang.reflect.Type;
17
import java.lang.reflect.TypeVariable;
18

19
import mockit.Capturing;
20
import mockit.Injectable;
21
import mockit.Mocked;
22
import mockit.internal.expectations.MockingFilters;
23
import mockit.internal.expectations.state.CascadingTypes;
24
import mockit.internal.expectations.state.ExecutingTest;
25
import mockit.internal.injection.InjectionProvider;
26
import mockit.internal.reflection.FieldReflection;
27
import mockit.internal.state.ParameterNames;
28
import mockit.internal.state.TestRun;
29
import mockit.internal.util.DefaultValues;
30
import mockit.internal.util.TestMethod;
31
import mockit.internal.util.TypeConversion;
32
import mockit.internal.util.Utilities;
33

34
import org.checkerframework.checker.index.qual.NonNegative;
35

36
@SuppressWarnings("EqualsAndHashcode")
37
public final class MockedType extends InjectionProvider {
38
    @Mocked
39
    private static final Object DUMMY = null;
1✔
40
    private static final int DUMMY_HASHCODE;
41

42
    static {
43
        int h = 0;
1✔
44

45
        try {
46
            Field dummyField = MockedType.class.getDeclaredField("DUMMY");
1✔
47
            Mocked mocked = dummyField.getAnnotation(Mocked.class);
1✔
48
            h = mocked.hashCode();
1✔
49
        } catch (NoSuchFieldException ignore) {
×
50
        }
1✔
51

52
        DUMMY_HASHCODE = h;
1✔
53
    }
1✔
54

55
    @Nullable
56
    public final Field field;
57
    final boolean fieldFromTestClass;
58
    private final int accessModifiers;
59
    @Nullable
60
    private final Mocked mocked;
61
    @Nullable
62
    private final Capturing capturing;
63
    @Nullable
64
    private final Class<?> parameterImplementationClass;
65
    public final boolean injectable;
66
    @Nullable
67
    Object providedValue;
68

69
    public MockedType(@NonNull Field field) {
70
        super(field.getGenericType(), field.getName());
1✔
71
        this.field = field;
1✔
72
        fieldFromTestClass = true;
1✔
73
        accessModifiers = field.getModifiers();
1✔
74
        mocked = field.getAnnotation(Mocked.class);
1✔
75
        capturing = field.getAnnotation(Capturing.class);
1✔
76
        parameterImplementationClass = null;
1✔
77
        Injectable injectableAnnotation = field.getAnnotation(Injectable.class);
1✔
78
        injectable = injectableAnnotation != null;
1✔
79
        providedValue = getProvidedInjectableValue(injectableAnnotation);
1✔
80
        registerCascadingAsNeeded();
1✔
81
    }
1✔
82

83
    @Nullable
84
    private Object getProvidedInjectableValue(@Nullable Injectable annotation) {
85
        if (annotation != null) {
1✔
86
            String value = annotation.value();
1✔
87

88
            if (!value.isEmpty()) {
1✔
89
                Class<?> injectableClass = getClassType();
1✔
90

91
                if (injectableClass != TypeVariable.class) {
1!
92
                    return TypeConversion.convertFromString(injectableClass, value);
1✔
93
                }
94
            }
95
        }
96

97
        return null;
1✔
98
    }
99

100
    private void registerCascadingAsNeeded() {
101
        if (isMockableType()) {
1✔
102
            Type mockedType = declaredType;
1✔
103

104
            if (!(mockedType instanceof TypeVariable<?>)) {
1✔
105
                ExecutingTest executingTest = TestRun.getExecutingTest();
1✔
106
                CascadingTypes types = executingTest.getCascadingTypes();
1✔
107
                types.add(fieldFromTestClass, mockedType);
1✔
108
            }
109
        }
110
    }
1✔
111

112
    MockedType(@NonNull TestMethod testMethod, @NonNegative int paramIndex, @NonNull Type parameterType,
113
            @NonNull Annotation[] annotationsOnParameter, @Nullable Class<?> parameterImplementationClass) {
114
        super(parameterType, ParameterNames.getName(testMethod, paramIndex));
1✔
115
        field = null;
1✔
116
        fieldFromTestClass = false;
1✔
117
        accessModifiers = 0;
1✔
118
        mocked = getAnnotation(annotationsOnParameter, Mocked.class);
1✔
119
        capturing = getAnnotation(annotationsOnParameter, Capturing.class);
1✔
120
        this.parameterImplementationClass = parameterImplementationClass;
1✔
121
        Injectable injectableAnnotation = getAnnotation(annotationsOnParameter, Injectable.class);
1✔
122
        injectable = injectableAnnotation != null;
1✔
123
        providedValue = getProvidedInjectableValue(injectableAnnotation);
1✔
124

125
        if (providedValue == null && parameterType instanceof Class<?>) {
1✔
126
            Class<?> parameterClass = (Class<?>) parameterType;
1✔
127

128
            if (parameterClass.isPrimitive()) {
1✔
129
                providedValue = DefaultValues.defaultValueForPrimitiveType(parameterClass);
1✔
130
            }
131
        }
132

133
        registerCascadingAsNeeded();
1✔
134
    }
1✔
135

136
    @Nullable
137
    private static <A extends Annotation> A getAnnotation(@NonNull Annotation[] annotations,
138
            @NonNull Class<A> annotation) {
139
        for (Annotation paramAnnotation : annotations) {
1✔
140
            if (paramAnnotation.annotationType() == annotation) {
1✔
141
                // noinspection unchecked
142
                return (A) paramAnnotation;
1✔
143
            }
144
        }
145

146
        return null;
1✔
147
    }
148

149
    MockedType(@NonNull String cascadingMethodName, @NonNull Type cascadedType) {
150
        super(cascadedType, cascadingMethodName);
1✔
151
        field = null;
1✔
152
        fieldFromTestClass = false;
1✔
153
        accessModifiers = 0;
1✔
154
        mocked = null;
1✔
155
        capturing = null;
1✔
156
        injectable = true;
1✔
157
        parameterImplementationClass = null;
1✔
158
    }
1✔
159

160
    @NonNull
161
    @Override
162
    public Class<?> getClassOfDeclaredType() {
163
        return getClassType();
×
164
    }
165

166
    /**
167
     * @return the class object corresponding to the type to be mocked, or <code>TypeVariable.class</code> in case the
168
     *         mocked type is a type variable (which usually occurs when the mocked type implements/extends multiple
169
     *         types)
170
     */
171
    @NonNull
172
    public Class<?> getClassType() {
173
        if (parameterImplementationClass != null) {
1!
174
            return parameterImplementationClass;
×
175
        }
176

177
        Type mockedType = declaredType;
1✔
178

179
        if (mockedType instanceof Class<?>) {
1✔
180
            return (Class<?>) mockedType;
1✔
181
        }
182

183
        if (mockedType instanceof ParameterizedType) {
1✔
184
            ParameterizedType parameterizedType = (ParameterizedType) mockedType;
1✔
185
            return (Class<?>) parameterizedType.getRawType();
1✔
186
        }
187

188
        // Occurs when declared type is a TypeVariable, usually having two or more bound types.
189
        // In such cases, there isn't a single class type.
190
        return TypeVariable.class;
1✔
191
    }
192

193
    boolean isMockableType() {
194
        if (mocked == null && !injectable && capturing == null) {
1✔
195
            return false;
1✔
196
        }
197

198
        Class<?> classType = Utilities.getClassType(declaredType);
1✔
199

200
        if (isUnmockableJREType(classType)) {
1✔
201
            return false;
1✔
202
        }
203

204
        MockingFilters.validateAsMockable(classType);
1✔
205

206
        if (injectable) {
1✔
207
            return !isJREValueType(classType) && !classType.isEnum();
1✔
208
        }
209

210
        return true;
1✔
211
    }
212

213
    private static boolean isUnmockableJREType(@NonNull Class<?> type) {
214
        return type.isPrimitive() || type.isArray() || type == Integer.class || type == String.class;
1✔
215
    }
216

217
    private static boolean isJREValueType(@NonNull Class<?> type) {
218
        return type == String.class || type == Boolean.class || type == Character.class
1!
219
                || Number.class.isAssignableFrom(type);
1✔
220
    }
221

222
    boolean isFinalFieldOrParameter() {
223
        return field == null || isFinal(accessModifiers);
1✔
224
    }
225

226
    boolean isClassInitializationToBeStubbedOut() {
227
        return mocked != null && mocked.stubOutClassInitialization();
1✔
228
    }
229

230
    boolean withInstancesToCapture() {
231
        return getMaxInstancesToCapture() > 0;
1✔
232
    }
233

234
    public int getMaxInstancesToCapture() {
235
        return capturing == null ? 0 : capturing.maxInstances();
1✔
236
    }
237

238
    @Nullable
239
    @Override
240
    public Object getValue(@Nullable Object owner) {
241
        if (field == null) {
1✔
242
            return providedValue;
1✔
243
        }
244

245
        Object value = FieldReflection.getFieldValue(field, owner);
1✔
246

247
        if (!injectable) {
1!
248
            return value;
×
249
        }
250

251
        Class<?> fieldType = field.getType();
1✔
252

253
        if (value == null) {
1✔
254
            if (providedValue != null) {
1✔
255
                return providedValue;
1✔
256
            }
257

258
            if (isFinalFieldOrParameter()) {
1✔
259
                return NULL;
1✔
260
            }
261

262
            if (fieldType == String.class) {
1✔
263
                return "";
1✔
264
            }
265

266
            return null;
1✔
267
        }
268

269
        if (providedValue == null || !fieldType.isPrimitive()) {
1!
270
            return value;
1✔
271
        }
272

273
        Object defaultValue = DefaultValues.defaultValueForPrimitiveType(fieldType);
1✔
274

275
        return value.equals(defaultValue) ? providedValue : value;
1!
276
    }
277

278
    @Override
279
    public int hashCode() {
280
        int result = declaredType.hashCode();
1✔
281

282
        if (isFinal(accessModifiers)) {
1!
283
            result *= 31;
×
284
        }
285

286
        if (injectable) {
1✔
287
            result *= 37;
1✔
288
        }
289

290
        if (mocked != null) {
1✔
291
            int h = mocked.hashCode();
1✔
292

293
            if (h != DUMMY_HASHCODE) {
1✔
294
                result = 31 * result + h;
1✔
295
            }
296
        }
297

298
        return result;
1✔
299
    }
300
}
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