• 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

73.77
/main/src/main/java/mockit/internal/injection/LifecycleMethods.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 mockit.internal.injection.InjectionPoint.JAKARTA_POST_CONSTRUCT_CLASS;
9
import static mockit.internal.injection.InjectionPoint.JAKARTA_SERVLET_CLASS;
10
import static mockit.internal.injection.InjectionPoint.JAVAX_POST_CONSTRUCT_CLASS;
11
import static mockit.internal.injection.InjectionPoint.JAVAX_SERVLET_CLASS;
12
import static mockit.internal.injection.InjectionPoint.isJakartaServlet;
13
import static mockit.internal.injection.InjectionPoint.isJavaxServlet;
14
import static mockit.internal.reflection.ParameterReflection.getParameterCount;
15
import static mockit.internal.util.Utilities.NO_ARGS;
16

17
import edu.umd.cs.findbugs.annotations.NonNull;
18
import edu.umd.cs.findbugs.annotations.Nullable;
19

20
import java.lang.annotation.Annotation;
21
import java.lang.reflect.Method;
22
import java.util.ArrayList;
23
import java.util.IdentityHashMap;
24
import java.util.List;
25
import java.util.Map;
26
import java.util.Map.Entry;
27

28
import mockit.internal.reflection.MethodReflection;
29
import mockit.internal.state.TestRun;
30

31
public final class LifecycleMethods {
32

33
    @NonNull
34
    private final List<Class<?>> classesSearched;
35

36
    @NonNull
37
    private final Map<Class<?>, Method> initializationMethods;
38

39
    @NonNull
40
    private final Map<Class<?>, Method> terminationMethods;
41

42
    @NonNull
43
    private final Map<Class<?>, Object> objectsWithTerminationMethodsToExecute;
44

45
    @Nullable
46
    private Object servletConfig;
47

48
    LifecycleMethods() {
1✔
49
        classesSearched = new ArrayList<>();
1✔
50
        initializationMethods = new IdentityHashMap<>();
1✔
51
        terminationMethods = new IdentityHashMap<>();
1✔
52
        objectsWithTerminationMethodsToExecute = new IdentityHashMap<>();
1✔
53
    }
1✔
54

55
    public void findLifecycleMethods(@NonNull Class<?> testedClass) {
56
        if (testedClass.isInterface() || classesSearched.contains(testedClass)) {
1!
57
            return;
1✔
58
        }
59

60
        boolean isServlet = isJakartaServlet(testedClass);
1✔
61
        if (!isServlet) {
1!
62
            isServlet = isJavaxServlet(testedClass);
1✔
63
        }
64
        Class<?> classWithLifecycleMethods = testedClass;
1✔
65

66
        do {
67
            findLifecycleMethodsInSingleClass(isServlet, classWithLifecycleMethods);
1✔
68
            classWithLifecycleMethods = classWithLifecycleMethods.getSuperclass();
1✔
69
        } while (classWithLifecycleMethods != Object.class);
1✔
70

71
        classesSearched.add(testedClass);
1✔
72
    }
1✔
73

74
    private void findLifecycleMethodsInSingleClass(boolean isServlet, @NonNull Class<?> classWithLifecycleMethods) {
75
        Method initializationMethod = null;
1✔
76
        Method terminationMethod = null;
1✔
77
        int methodsFoundInSameClass = 0;
1✔
78

79
        for (Method method : classWithLifecycleMethods.getDeclaredMethods()) {
1✔
80
            if (method.isSynthetic()) {
1✔
81
                continue;
1✔
82
            }
83

84
            if (initializationMethod == null && isInitializationMethod(method, isServlet)) {
1✔
85
                initializationMethods.put(classWithLifecycleMethods, method);
1✔
86
                initializationMethod = method;
1✔
87
                methodsFoundInSameClass++;
1✔
88
            } else if (terminationMethod == null && isTerminationMethod(method, isServlet)) {
1!
89
                terminationMethods.put(classWithLifecycleMethods, method);
1✔
90
                terminationMethod = method;
1✔
91
                methodsFoundInSameClass++;
1✔
92
            }
93

94
            if (methodsFoundInSameClass == 2) {
1✔
95
                break;
1✔
96
            }
97
        }
98
    }
1✔
99

100
    private static boolean isInitializationMethod(@NonNull Method method, boolean isServlet) {
101
        if (hasLifecycleAnnotationJakarta(method, true) || hasLifecycleAnnotationJavax(method, true)) {
1!
102
            return true;
1✔
103
        }
104

105
        if (isServlet && "init".equals(method.getName())) {
1!
106
            Class<?>[] parameterTypes = method.getParameterTypes();
×
107

108
            if (parameterTypes.length != 1) {
×
109
                return false;
×
110
            }
111
            return (JAKARTA_SERVLET_CLASS != null && parameterTypes[0] == jakarta.servlet.ServletConfig.class)
×
112
                    || (JAVAX_SERVLET_CLASS != null && parameterTypes[0] == javax.servlet.ServletConfig.class);
113
        }
114

115
        return false;
1✔
116
    }
117

118
    private static boolean hasLifecycleAnnotationJakarta(@NonNull Method method, boolean postConstruct) {
119
        if (JAKARTA_POST_CONSTRUCT_CLASS == null) {
1!
120
            return false;
×
121
        }
122

123
        try {
124
            Class<? extends Annotation> lifecycleAnnotation = postConstruct ? jakarta.annotation.PostConstruct.class
1✔
125
                    : jakarta.annotation.PreDestroy.class;
1✔
126

127
            if (method.isAnnotationPresent(lifecycleAnnotation)) {
1✔
128
                return true;
1✔
129
            }
130
        } catch (NoClassDefFoundError ignore) {
×
131
            /* can occur on JDK 9 */ }
1✔
132

133
        return false;
1✔
134
    }
135

136
    private static boolean hasLifecycleAnnotationJavax(@NonNull Method method, boolean postConstruct) {
137
        if (JAVAX_POST_CONSTRUCT_CLASS == null) {
1!
138
            return false;
×
139
        }
140

141
        try {
142
            Class<? extends Annotation> lifecycleAnnotation = postConstruct ? javax.annotation.PostConstruct.class
1✔
143
                    : javax.annotation.PreDestroy.class;
1✔
144

145
            if (method.isAnnotationPresent(lifecycleAnnotation)) {
1!
146
                return true;
×
147
            }
148
        } catch (NoClassDefFoundError ignore) {
×
149
            /* can occur on JDK 9 */ }
1✔
150

151
        return false;
1✔
152
    }
153

154
    private static boolean isTerminationMethod(@NonNull Method method, boolean isServlet) {
155
        return hasLifecycleAnnotationJakarta(method, false) || hasLifecycleAnnotationJavax(method, false)
1!
156
                || isServlet && "destroy".equals(method.getName()) && getParameterCount(method) == 0;
1!
157
    }
158

159
    public void executeInitializationMethodsIfAny(@NonNull Class<?> testedClass, @NonNull Object testedObject) {
160
        Class<?> superclass = testedClass.getSuperclass();
1✔
161

162
        if (superclass != Object.class) {
1✔
163
            executeInitializationMethodsIfAny(superclass, testedObject);
1✔
164
        }
165

166
        Method postConstructMethod = initializationMethods.get(testedClass);
1✔
167

168
        if (postConstructMethod != null) {
1✔
169
            executeInitializationMethod(testedObject, postConstructMethod);
1✔
170
        }
171

172
        Method preDestroyMethod = terminationMethods.get(testedClass);
1✔
173

174
        if (preDestroyMethod != null) {
1✔
175
            objectsWithTerminationMethodsToExecute.put(testedClass, testedObject);
1✔
176
        }
177
    }
1✔
178

179
    private void executeInitializationMethod(@NonNull Object testedObject, @NonNull Method initializationMethod) {
180
        Object[] args = NO_ARGS;
1✔
181

182
        if ("init".equals(initializationMethod.getName()) && getParameterCount(initializationMethod) == 1) {
1!
183
            args = new Object[] { servletConfig };
×
184
        }
185

186
        TestRun.exitNoMockingZone();
1✔
187

188
        try {
189
            MethodReflection.invoke(testedObject, initializationMethod, args);
1✔
190
        } finally {
191
            TestRun.enterNoMockingZone();
1✔
192
        }
193
    }
1✔
194

195
    void executeTerminationMethodsIfAny() {
196
        try {
197
            for (Entry<Class<?>, Object> testedClassAndObject : objectsWithTerminationMethodsToExecute.entrySet()) {
1✔
198
                executeTerminationMethod(testedClassAndObject.getKey(), testedClassAndObject.getValue());
1✔
199
            }
1✔
200
        } finally {
201
            objectsWithTerminationMethodsToExecute.clear();
1✔
202
        }
203
    }
1✔
204

205
    private void executeTerminationMethod(@NonNull Class<?> testedClass, @NonNull Object testedObject) {
206
        Method terminationMethod = terminationMethods.get(testedClass);
1✔
207
        TestRun.exitNoMockingZone();
1✔
208

209
        try {
210
            MethodReflection.invoke(testedObject, terminationMethod);
1✔
211
        } catch (RuntimeException | AssertionError ignore) {
×
212
        } finally {
213
            TestRun.enterNoMockingZone();
1✔
214
        }
215
    }
1✔
216

217
    void getServletConfigForInitMethodsIfAny(@NonNull List<? extends InjectionProvider> injectables,
218
            @NonNull Object testClassInstance) {
219
        for (InjectionProvider injectable : injectables) {
1✔
220
            // Try Jakarta first
221
            if (JAKARTA_SERVLET_CLASS != null && injectable.getDeclaredType() == jakarta.servlet.ServletConfig.class) {
1!
222
                servletConfig = injectable.getValue(testClassInstance);
×
223
                break;
×
224
            }
225

226
            // Then try Javax
227
            if (JAVAX_SERVLET_CLASS != null && injectable.getDeclaredType() == javax.servlet.ServletConfig.class) {
1!
228
                servletConfig = injectable.getValue(testClassInstance);
×
229
                break;
×
230
            }
231
        }
1✔
232
    }
1✔
233

234
}
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