• 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

95.83
/main/src/main/java/mockit/internal/expectations/mocking/BaseTypeRedefinition.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.isAbstract;
9
import static java.lang.reflect.Modifier.isPublic;
10

11
import static mockit.internal.util.GeneratedClasses.getNameForGeneratedClass;
12
import static mockit.internal.util.Utilities.JAVA8;
13
import static mockit.internal.util.Utilities.getClassType;
14

15
import edu.umd.cs.findbugs.annotations.NonNull;
16
import edu.umd.cs.findbugs.annotations.Nullable;
17

18
import java.lang.instrument.ClassDefinition;
19
import java.lang.reflect.ParameterizedType;
20
import java.lang.reflect.Proxy;
21
import java.lang.reflect.Type;
22
import java.lang.reflect.TypeVariable;
23
import java.util.ArrayList;
24
import java.util.HashMap;
25
import java.util.List;
26
import java.util.Map;
27

28
import mockit.asm.classes.ClassReader;
29
import mockit.asm.classes.ClassVisitor;
30
import mockit.asm.jvmConstants.ClassVersion;
31
import mockit.internal.ClassFile;
32
import mockit.internal.classGeneration.ImplementationClass;
33
import mockit.internal.expectations.mocking.InstanceFactory.ClassInstanceFactory;
34
import mockit.internal.expectations.mocking.InstanceFactory.InterfaceInstanceFactory;
35
import mockit.internal.reflection.ConstructorReflection;
36
import mockit.internal.reflection.EmptyProxy.Impl;
37
import mockit.internal.state.TestRun;
38
import mockit.internal.util.ClassLoad;
39
import mockit.internal.util.VisitInterruptedException;
40

41
class BaseTypeRedefinition {
42
    private static final ClassDefinition[] CLASS_DEFINITIONS = {};
1✔
43

44
    private static final class MockedClass {
45
        @Nullable
46
        final InstanceFactory instanceFactory;
47
        @NonNull
48
        final ClassDefinition[] mockedClassDefinitions;
49

50
        MockedClass(@Nullable InstanceFactory instanceFactory, @NonNull ClassDefinition[] classDefinitions) {
1✔
51
            this.instanceFactory = instanceFactory;
1✔
52
            mockedClassDefinitions = classDefinitions;
1✔
53
        }
1✔
54

55
        void redefineClasses() {
56
            TestRun.mockFixture().redefineClasses(mockedClassDefinitions);
1✔
57
        }
1✔
58
    }
59

60
    @NonNull
61
    private static final Map<Integer, MockedClass> mockedClasses = new HashMap<>();
1✔
62
    @NonNull
63
    private static final Map<Type, Class<?>> mockImplementations = new HashMap<>();
1✔
64

65
    Class<?> targetClass;
66
    @Nullable
67
    MockedType typeMetadata;
68
    @Nullable
69
    private InstanceFactory instanceFactory;
70
    @Nullable
71
    private List<ClassDefinition> mockedClassDefinitions;
72

73
    BaseTypeRedefinition() {
1✔
74
    }
1✔
75

76
    BaseTypeRedefinition(@NonNull MockedType typeMetadata) {
1✔
77
        targetClass = typeMetadata.getClassType();
1✔
78
        this.typeMetadata = typeMetadata;
1✔
79
    }
1✔
80

81
    @Nullable
82
    final InstanceFactory redefineType(@NonNull Type typeToMock) {
83
        if (targetClass == TypeVariable.class || targetClass.isInterface()) {
1✔
84
            createMockedInterfaceImplementationAndInstanceFactory(typeToMock);
1✔
85
        } else {
86
            if (typeMetadata == null || !typeMetadata.isClassInitializationToBeStubbedOut()) {
1!
87
                TestRun.ensureThatClassIsInitialized(targetClass);
1✔
88
            }
89
            redefineTargetClassAndCreateInstanceFactory(typeToMock);
1✔
90
        }
91

92
        if (instanceFactory != null) {
1!
93
            Class<?> mockedType = getClassType(typeToMock);
1✔
94
            TestRun.mockFixture().registerInstanceFactoryForMockedType(mockedType, instanceFactory);
1✔
95
        }
96

97
        return instanceFactory;
1✔
98
    }
99

100
    private void createMockedInterfaceImplementationAndInstanceFactory(@NonNull Type interfaceToMock) {
101
        Class<?> mockedInterface = interfaceToMock(interfaceToMock);
1✔
102
        Object mockedInstance;
103

104
        if (mockedInterface == null) {
1✔
105
            mockedInstance = createMockInterfaceImplementationUsingStandardProxy(interfaceToMock);
1✔
106
        } else {
107
            mockedInstance = createMockInterfaceImplementationDirectly(interfaceToMock);
1✔
108
        }
109

110
        redefinedImplementedInterfacesIfRunningOnJava8(targetClass);
1✔
111
        instanceFactory = new InterfaceInstanceFactory(mockedInstance);
1✔
112
    }
1✔
113

114
    @Nullable
115
    private static Class<?> interfaceToMock(@NonNull Type typeToMock) {
116
        while (true) {
117
            if (typeToMock instanceof Class<?>) {
1✔
118
                Class<?> theInterface = (Class<?>) typeToMock;
1✔
119

120
                if (isPublic(theInterface.getModifiers()) && !theInterface.isAnnotation()) {
1✔
121
                    return theInterface;
1✔
122
                }
123
            } else if (typeToMock instanceof ParameterizedType) {
1✔
124
                typeToMock = ((ParameterizedType) typeToMock).getRawType();
1✔
125
                continue;
1✔
126
            }
127

128
            return null;
1✔
129
        }
130
    }
131

132
    @NonNull
133
    private Object createMockInterfaceImplementationUsingStandardProxy(@NonNull Type typeToMock) {
134
        ClassLoader loader = getClass().getClassLoader();
1✔
135
        Object mockedInstance = Impl.newEmptyProxy(loader, typeToMock);
1✔
136
        targetClass = mockedInstance.getClass();
1✔
137
        redefineClass(targetClass);
1✔
138
        return mockedInstance;
1✔
139
    }
140

141
    @NonNull
142
    private Object createMockInterfaceImplementationDirectly(@NonNull Type interfaceToMock) {
143
        Class<?> previousMockImplementationClass = mockImplementations.get(interfaceToMock);
1✔
144

145
        if (previousMockImplementationClass == null) {
1✔
146
            generateNewMockImplementationClassForInterface(interfaceToMock);
1✔
147
            mockImplementations.put(interfaceToMock, targetClass);
1✔
148
        } else {
149
            targetClass = previousMockImplementationClass;
1✔
150
        }
151

152
        return ConstructorReflection.newInstanceUsingDefaultConstructor(targetClass);
1✔
153
    }
154

155
    private void redefineClass(@NonNull Class<?> realClass) {
156
        ClassReader classReader = ClassFile.createReaderOrGetFromCache(realClass);
1✔
157

158
        if (realClass.isInterface() && classReader.getVersion() < ClassVersion.V8) {
1✔
159
            return;
1✔
160
        }
161

162
        ClassLoader loader = realClass.getClassLoader();
1✔
163
        MockedClassModifier modifier = createClassModifier(loader, classReader);
1✔
164
        redefineClass(realClass, classReader, modifier);
1✔
165
    }
1✔
166

167
    @NonNull
168
    private MockedClassModifier createClassModifier(@Nullable ClassLoader loader, @NonNull ClassReader classReader) {
169
        MockedClassModifier modifier = new MockedClassModifier(loader, classReader, typeMetadata);
1✔
170
        configureClassModifier(modifier);
1✔
171
        return modifier;
1✔
172
    }
173

174
    void configureClassModifier(@NonNull MockedClassModifier modifier) {
175
    }
1✔
176

177
    private void generateNewMockImplementationClassForInterface(@NonNull final Type interfaceToMock) {
178
        ImplementationClass<?> implementationGenerator = new ImplementationClass<>(interfaceToMock) {
1✔
179
            @NonNull
180
            @Override
181
            protected ClassVisitor createMethodBodyGenerator(@NonNull ClassReader cr) {
182
                return new InterfaceImplementationGenerator(cr, interfaceToMock, generatedClassName);
1✔
183
            }
184
        };
185

186
        targetClass = implementationGenerator.generateClass();
1✔
187
    }
1✔
188

189
    private void redefinedImplementedInterfacesIfRunningOnJava8(@NonNull Class<?> aClass) {
190
        if (JAVA8) {
1!
191
            redefineImplementedInterfaces(aClass.getInterfaces());
1✔
192
        }
193
    }
1✔
194

195
    final boolean redefineMethodsAndConstructorsInTargetType() {
196
        return redefineClassAndItsSuperClasses(targetClass);
1✔
197
    }
198

199
    private boolean redefineClassAndItsSuperClasses(@NonNull Class<?> realClass) {
200
        ClassLoader loader = realClass.getClassLoader();
1✔
201
        ClassReader classReader = ClassFile.createReaderOrGetFromCache(realClass);
1✔
202
        MockedClassModifier modifier = createClassModifier(loader, classReader);
1✔
203

204
        try {
205
            redefineClass(realClass, classReader, modifier);
1✔
206
        } catch (VisitInterruptedException ignore) {
×
207
            // As defined in MockedClassModifier, some critical JRE classes have all methods excluded from mocking by
208
            // default. This exception occurs when they are visited.
209
            // In this case, we simply stop class redefinition for the rest of the class hierarchy.
210
            return false;
×
211
        }
1✔
212

213
        redefineElementSubclassesOfEnumTypeIfAny(modifier.enumSubclasses);
1✔
214
        redefinedImplementedInterfacesIfRunningOnJava8(realClass);
1✔
215

216
        Class<?> superClass = realClass.getSuperclass();
1✔
217
        boolean redefined = true;
1✔
218

219
        if (superClass != null && superClass != Object.class && superClass != Proxy.class && superClass != Enum.class) {
1!
220
            redefined = redefineClassAndItsSuperClasses(superClass);
1✔
221
        }
222

223
        return redefined;
1✔
224
    }
225

226
    private void redefineClass(@NonNull Class<?> realClass, @NonNull ClassReader classReader,
227
            @NonNull MockedClassModifier modifier) {
228
        classReader.accept(modifier);
1✔
229

230
        if (modifier.wasModified()) {
1✔
231
            byte[] modifiedClass = modifier.toByteArray();
1✔
232
            applyClassRedefinition(realClass, modifiedClass);
1✔
233
        }
234
    }
1✔
235

236
    void applyClassRedefinition(@NonNull Class<?> realClass, @NonNull byte[] modifiedClass) {
237
        ClassDefinition classDefinition = new ClassDefinition(realClass, modifiedClass);
1✔
238
        TestRun.mockFixture().redefineClasses(classDefinition);
1✔
239

240
        if (mockedClassDefinitions != null) {
1✔
241
            mockedClassDefinitions.add(classDefinition);
1✔
242
        }
243
    }
1✔
244

245
    private void redefineElementSubclassesOfEnumTypeIfAny(@Nullable List<String> enumSubclasses) {
246
        if (enumSubclasses != null) {
1✔
247
            for (String enumSubclassDesc : enumSubclasses) {
1✔
248
                Class<?> enumSubclass = ClassLoad.loadByInternalName(enumSubclassDesc);
1✔
249
                redefineClass(enumSubclass);
1✔
250
            }
1✔
251
        }
252
    }
1✔
253

254
    private void redefineImplementedInterfaces(@NonNull Class<?>[] implementedInterfaces) {
255
        for (Class<?> implementedInterface : implementedInterfaces) {
1✔
256
            redefineClass(implementedInterface);
1✔
257
            redefineImplementedInterfaces(implementedInterface.getInterfaces());
1✔
258
        }
259
    }
1✔
260

261
    private void redefineTargetClassAndCreateInstanceFactory(@NonNull Type typeToMock) {
262
        Integer mockedClassId = redefineClassesFromCache();
1✔
263

264
        if (mockedClassId == null) {
1✔
265
            return;
1✔
266
        }
267

268
        boolean redefined = redefineMethodsAndConstructorsInTargetType();
1✔
269
        instanceFactory = createInstanceFactory(typeToMock);
1✔
270

271
        if (redefined) {
1!
272
            storeRedefinedClassesInCache(mockedClassId);
1✔
273
        }
274
    }
1✔
275

276
    @NonNull
277
    final InstanceFactory createInstanceFactory(@NonNull Type typeToMock) {
278
        Class<?> classToInstantiate = targetClass;
1✔
279

280
        if (isAbstract(classToInstantiate.getModifiers())) {
1✔
281
            classToInstantiate = generateConcreteSubclassForAbstractType(typeToMock);
1✔
282
        }
283

284
        return new ClassInstanceFactory(classToInstantiate);
1✔
285
    }
286

287
    @Nullable
288
    private Integer redefineClassesFromCache() {
289
        // noinspection ConstantConditions
290
        Integer mockedClassId = typeMetadata.hashCode();
1✔
291
        MockedClass mockedClass = mockedClasses.get(mockedClassId);
1✔
292

293
        if (mockedClass != null) {
1✔
294
            mockedClass.redefineClasses();
1✔
295
            instanceFactory = mockedClass.instanceFactory;
1✔
296
            return null;
1✔
297
        }
298

299
        mockedClassDefinitions = new ArrayList<>();
1✔
300
        return mockedClassId;
1✔
301
    }
302

303
    private void storeRedefinedClassesInCache(@NonNull Integer mockedClassId) {
304
        assert mockedClassDefinitions != null;
1!
305
        ClassDefinition[] classDefs = mockedClassDefinitions.toArray(CLASS_DEFINITIONS);
1✔
306
        MockedClass mockedClass = new MockedClass(instanceFactory, classDefs);
1✔
307

308
        mockedClasses.put(mockedClassId, mockedClass);
1✔
309
    }
1✔
310

311
    @NonNull
312
    private Class<?> generateConcreteSubclassForAbstractType(@NonNull final Type typeToMock) {
313
        final String subclassName = getNameForConcreteSubclassToCreate();
1✔
314

315
        return new ImplementationClass<>(targetClass, subclassName) {
1✔
316
            @NonNull
317
            @Override
318
            protected ClassVisitor createMethodBodyGenerator(@NonNull ClassReader cr) {
319
                return new SubclassGenerationModifier(targetClass, typeToMock, cr, subclassName, false);
1✔
320
            }
321
        }.generateClass();
1✔
322
    }
323

324
    @NonNull
325
    private String getNameForConcreteSubclassToCreate() {
326
        String mockId = typeMetadata == null ? null : typeMetadata.getName();
1✔
327
        return getNameForGeneratedClass(targetClass, mockId);
1✔
328
    }
329
}
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