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

hazendaz / jmockit1 / 458

08 Nov 2025 12:44AM UTC coverage: 72.238% (-0.04%) from 72.273%
458

push

github

web-flow
Merge pull request #406 from hazendaz/junit5-ext

[junit] Cleanup extension printing warning and better null handling

5675 of 8360 branches covered (67.88%)

Branch coverage included in aggregate %.

0 of 4 new or added lines in 1 file covered. (0.0%)

5 existing lines in 1 file now uncovered.

11936 of 16019 relevant lines covered (74.51%)

0.75 hits per line

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

57.69
/main/src/main/java/mockit/integration/junit5/JMockitExtension.java
1
/*
2
 * Copyright (c) 2006 JMockit developers
3
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
4
 */
5
package mockit.integration.junit5;
6

7
import static mockit.internal.util.StackTrace.filterStackTrace;
8

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

12
import java.lang.reflect.Method;
13
import java.util.Arrays;
14
import java.util.stream.Collectors;
15

16
import mockit.Capturing;
17
import mockit.Injectable;
18
import mockit.Mocked;
19
import mockit.Tested;
20
import mockit.integration.TestRunnerDecorator;
21
import mockit.internal.expectations.RecordAndReplayExecution;
22
import mockit.internal.state.SavePoint;
23
import mockit.internal.state.TestRun;
24
import mockit.internal.util.Utilities;
25

26
import org.junit.jupiter.api.BeforeAll;
27
import org.junit.jupiter.api.BeforeEach;
28
import org.junit.jupiter.api.Nested;
29
import org.junit.jupiter.api.extension.AfterAllCallback;
30
import org.junit.jupiter.api.extension.AfterEachCallback;
31
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
32
import org.junit.jupiter.api.extension.BeforeAllCallback;
33
import org.junit.jupiter.api.extension.BeforeEachCallback;
34
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
35
import org.junit.jupiter.api.extension.ExtensionContext;
36
import org.junit.jupiter.api.extension.ParameterContext;
37
import org.junit.jupiter.api.extension.ParameterResolver;
38
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
39
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
40

41
public final class JMockitExtension extends TestRunnerDecorator implements BeforeAllCallback, AfterAllCallback,
1✔
42
        TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback,
43
        AfterTestExecutionCallback, ParameterResolver, TestExecutionExceptionHandler {
44
    @Nullable
45
    private SavePoint savePointForTestClass;
46
    @Nullable
47
    private SavePoint savePointForTest;
48
    @Nullable
49
    private SavePoint savePointForTestMethod;
50
    @Nullable
51
    private Throwable thrownByTest;
52
    private Object[] parameterValues;
53
    private ParamValueInitContext initContext = new ParamValueInitContext(null, null, null,
1✔
54
            "No callbacks have been processed, preventing parameter population");
55

56
    @Override
57
    public void beforeAll(@NonNull ExtensionContext context) {
58
        if (!isRegularTestClass(context)) {
1!
59
            return;
×
60
        }
61

62
        @Nullable
63
        Class<?> testClass = context.getTestClass().orElse(null);
1✔
64
        savePointForTestClass = new SavePoint();
1✔
65
        TestRun.setCurrentTestClass(testClass);
1✔
66

67
        if (testClass == null) {
1!
68
            initContext = new ParamValueInitContext(null, null, null,
×
69
                    "@BeforeAll setup failed to acquire 'Class' of test");
70
            return;
×
71
        }
72

73
        // @BeforeAll can be used on instance methods depending on @TestInstance(PER_CLASS) usage
74
        Object testInstance = context.getTestInstance().orElse(null);
1✔
75
        Method beforeAllMethod = Utilities.getAnnotatedDeclaredMethod(testClass, BeforeAll.class);
1✔
76
        if (testInstance == null) {
1!
77
            initContext = new ParamValueInitContext(null, testClass, beforeAllMethod,
1✔
78
                    "@BeforeAll setup failed to acquire instance of test class");
79
            return;
1✔
80
        }
81

82
        if (beforeAllMethod != null) {
×
83
            initContext = new ParamValueInitContext(testInstance, testClass, beforeAllMethod, null);
×
84
            parameterValues = createInstancesForAnnotatedParameters(testInstance, beforeAllMethod, null);
×
85
        }
86
    }
×
87

88
    private static boolean isRegularTestClass(@NonNull ExtensionContext context) {
89
        Class<?> testClass = context.getTestClass().orElse(null);
1✔
90
        return testClass != null && !testClass.isAnnotationPresent(Nested.class);
1!
91
    }
92

93
    @Override
94
    public void postProcessTestInstance(@NonNull Object testInstance, @NonNull ExtensionContext context) {
95
        if (!isRegularTestClass(context)) {
1!
96
            return;
×
97
        }
98

99
        TestRun.enterNoMockingZone();
1✔
100

101
        try {
102
            handleMockFieldsForWholeTestClass(testInstance);
1✔
103
        } finally {
104
            TestRun.exitNoMockingZone();
1✔
105
        }
106

107
        TestRun.setRunningIndividualTest(testInstance);
1✔
108
    }
1✔
109

110
    @Override
111
    public void beforeEach(@NonNull ExtensionContext context) {
112
        Object testInstance = context.getTestInstance().orElse(null);
1✔
113
        Class<?> testClass = context.getTestClass().orElse(null);
1✔
114
        if (testInstance == null) {
1!
115
            initContext = new ParamValueInitContext(null, null, null,
×
116
                    "@BeforeEach setup failed to acquire instance of test class");
117
            return;
×
118
        }
119

120
        TestRun.prepareForNextTest();
1✔
121
        TestRun.enterNoMockingZone();
1✔
122

123
        try {
124
            savePointForTest = new SavePoint();
1✔
125
            createInstancesForTestedFieldsBeforeSetup(testInstance);
1✔
126

127
            if (testClass == null) {
1!
128
                initContext = new ParamValueInitContext(null, null, null,
×
129
                        "@BeforeEach setup failed to acquire Class<?> of test");
130
                return;
×
131
            }
132

133
            Method beforeEachMethod = Utilities.getAnnotatedDeclaredMethod(testClass, BeforeEach.class);
1✔
134
            if (beforeEachMethod != null) {
1✔
135
                initContext = new ParamValueInitContext(testInstance, testClass, beforeEachMethod, null);
1✔
136
                parameterValues = createInstancesForAnnotatedParameters(testInstance, beforeEachMethod, null);
1✔
137
            }
138
        } finally {
139
            TestRun.exitNoMockingZone();
1✔
140
        }
141
    }
1✔
142

143
    @Override
144
    public void beforeTestExecution(@NonNull ExtensionContext context) {
145
        Class<?> testClass = context.getTestClass().orElse(null);
1✔
146
        Method testMethod = context.getTestMethod().orElse(null);
1✔
147
        Object testInstance = context.getTestInstance().orElse(null);
1✔
148

149
        if (testMethod == null || testInstance == null) {
1!
150
            initContext = new ParamValueInitContext(testInstance, testClass, testMethod,
×
151
                    "@Test failed to acquire instance of test class, or target method");
152
            return;
×
153
        }
154

155
        TestRun.enterNoMockingZone();
1✔
156

157
        try {
158
            savePointForTestMethod = new SavePoint();
1✔
159
            createInstancesForTestedFieldsFromBaseClasses(testInstance);
1✔
160
            initContext = new ParamValueInitContext(testInstance, testClass, testMethod, null);
1✔
161
            parameterValues = createInstancesForAnnotatedParameters(testInstance, testMethod, null);
1✔
162
            createInstancesForTestedFields(testInstance);
1✔
163
        } finally {
164
            TestRun.exitNoMockingZone();
1✔
165
        }
166

167
        TestRun.setRunningIndividualTest(testInstance);
1✔
168
    }
1✔
169

170
    @Override
171
    public boolean supportsParameter(@NonNull ParameterContext parameterContext,
172
            @NonNull ExtensionContext extensionContext) {
173
        return parameterContext.isAnnotated(Tested.class) || parameterContext.isAnnotated(Mocked.class)
1✔
174
                || parameterContext.isAnnotated(Injectable.class) || parameterContext.isAnnotated(Capturing.class);
1!
175
    }
176

177
    @Override
178
    public Object resolveParameter(@NonNull ParameterContext parameterContext,
179
            @NonNull ExtensionContext extensionContext) {
180
        int parameterIndex = parameterContext.getIndex();
1✔
181
        if (parameterValues == null) {
1!
182
            String warning = initContext.warning;
×
183
            StringBuilder exceptionMessage = new StringBuilder(
×
184
                    "JMockit failed to provide parameters to JUnit 5 ParameterResolver.");
185
            if (warning != null) {
×
186
                exceptionMessage.append("\nAdditional info: ").append(warning);
×
187
            }
188
            exceptionMessage.append("\n - Class: ").append(initContext.displayClass());
×
189
            exceptionMessage.append("\n - Method: ").append(initContext.displayMethod());
×
190
            throw new IllegalStateException(exceptionMessage.toString());
×
191
        }
192
        return parameterValues[parameterIndex];
1✔
193
    }
194

195
    @Override
196
    public void handleTestExecutionException(@NonNull ExtensionContext context, @NonNull Throwable throwable)
197
            throws Throwable {
198
        thrownByTest = throwable;
×
199
        throw throwable;
×
200
    }
201

202
    @Override
203
    public void afterTestExecution(@NonNull ExtensionContext context) {
204
        if (savePointForTestMethod == null) {
1!
205
            return;
×
206
        }
207

208
        TestRun.enterNoMockingZone();
1✔
209

210
        try {
211
            savePointForTestMethod.rollback();
1✔
212
            savePointForTestMethod = null;
1✔
213

214
            if (thrownByTest != null) {
1!
215
                filterStackTrace(thrownByTest);
×
216
            }
217

218
            Error expectationsFailure = RecordAndReplayExecution.endCurrentReplayIfAny();
1✔
219
            clearTestedObjectsIfAny();
1✔
220

221
            if (expectationsFailure != null) {
1!
222
                filterStackTrace(expectationsFailure);
×
223
                throw expectationsFailure;
×
224
            }
225
        } finally {
226
            TestRun.finishCurrentTestExecution();
1✔
227
            TestRun.exitNoMockingZone();
1✔
228
        }
229
    }
1✔
230

231
    @Override
232
    public void afterEach(@NonNull ExtensionContext context) {
233
        if (savePointForTest != null) {
1!
234
            savePointForTest.rollback();
1✔
235
            savePointForTest = null;
1✔
236
        }
237
    }
1✔
238

239
    @Override
240
    public void afterAll(@NonNull ExtensionContext context) {
241
        if (savePointForTestClass != null && isRegularTestClass(context)) {
1!
242
            savePointForTestClass.rollback();
1✔
243
            savePointForTestClass = null;
1✔
244

245
            clearFieldTypeRedefinitions();
1✔
246
            TestRun.setCurrentTestClass(null);
1✔
247
        }
248
    }
1✔
249

250
    private static class ParamValueInitContext {
251
        private final Object instance;
252
        private final Class<?> clazz;
253
        private final Method method;
254
        private final String warning;
255

256
        ParamValueInitContext(Object instance, Class<?> clazz, Method method, String warning) {
1✔
257
            this.instance = instance;
1✔
258
            this.clazz = clazz;
1✔
259
            this.method = method;
1✔
260
            this.warning = warning;
1✔
261
        }
1✔
262

263
        boolean isBeforeAllMethod() {
NEW
264
            return method != null && method.getDeclaredAnnotation(BeforeAll.class) != null;
×
265
        }
266

267
        boolean isBeforeEachMethod() {
NEW
268
            return method != null && method.getDeclaredAnnotation(BeforeEach.class) != null;
×
269
        }
270

271
        String displayClass() {
NEW
272
            return clazz == null ? "<no class reference>" : clazz.getName();
×
273
        }
274

275
        String displayMethod() {
276
            if (method == null) {
×
277
                return "<no method reference>";
×
278
            }
279
            String methodPrefix = isBeforeAllMethod() ? "@BeforeAll " : isBeforeEachMethod() ? "@BeforeEach " : "";
×
280
            String args = Arrays.stream(method.getParameterTypes()).map(Class::getName)
×
281
                    .collect(Collectors.joining(", "));
×
282
            return methodPrefix + method.getName() + "(" + args + ")";
×
283
        }
284

285
        @Override
286
        public String toString() {
NEW
287
            return "ParamContext{hasInstance=" + (instance == null ? "false" : "true") + ", class=" + clazz
×
288
                    + ", method=" + method + ", warning=" + warning + "}";
289
        }
290
    }
291
}
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