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

hazendaz / jmockit1 / 551

29 Nov 2025 11:34PM UTC coverage: 72.096% (-0.1%) from 72.2%
551

push

github

web-flow
Merge pull request #424 from hazendaz/expectedExceptionAnnotation

Introduction of 'ExpectedException' annotation

5685 of 8390 branches covered (67.76%)

Branch coverage included in aggregate %.

22 of 30 new or added lines in 1 file covered. (73.33%)

14 existing lines in 3 files now uncovered.

11933 of 16047 relevant lines covered (74.36%)

0.74 hits per line

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

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

8
import static mockit.internal.reflection.ParameterReflection.getParameterCount;
9

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

13
import java.lang.reflect.Method;
14
import java.util.Collections;
15
import java.util.List;
16

17
import mockit.internal.expectations.RecordAndReplayExecution;
18
import mockit.internal.expectations.invocation.MissingInvocation;
19
import mockit.internal.expectations.invocation.UnexpectedInvocation;
20
import mockit.internal.expectations.mocking.FieldTypeRedefinitions;
21
import mockit.internal.expectations.mocking.ParameterTypeRedefinitions;
22
import mockit.internal.expectations.mocking.TypeRedefinitions;
23
import mockit.internal.injection.InjectionProvider;
24
import mockit.internal.injection.TestedClassInstantiations;
25
import mockit.internal.injection.TestedParameters;
26
import mockit.internal.state.SavePoint;
27
import mockit.internal.state.TestRun;
28
import mockit.internal.util.ParameterNameExtractor;
29
import mockit.internal.util.StackTrace;
30
import mockit.internal.util.TestMethod;
31

32
/**
33
 * Base class for "test runner decorators", which provide integration between JMockit and specific test runners from
34
 * JUnit and TestNG.
35
 */
36
public class TestRunnerDecorator {
37
    @Nullable
38
    private static SavePoint savePointForTestClass;
39
    @Nullable
40
    private static SavePoint savePointForTest;
41

42
    /**
43
     * A "volatile boolean" is as good as a java.util.concurrent.atomic.AtomicBoolean here, since we only need the basic
44
     * get/set operations.
45
     */
46
    protected volatile boolean shouldPrepareForNextTest;
47

48
    protected TestRunnerDecorator() {
1✔
49
        shouldPrepareForNextTest = true;
1✔
50
    }
1✔
51

52
    protected static void updateTestClassState(@Nullable Object target, @NonNull Class<?> testClass) {
53
        testClass = getActualTestClass(testClass);
1✔
54

55
        try {
56
            handleSwitchToNewTestClassIfApplicable(testClass);
1✔
57

58
            if (target != null) {
1✔
59
                handleMockFieldsForWholeTestClass(target);
1✔
60
            }
61
        } catch (Error e) {
×
62
            try {
63
                rollbackForTestClass();
×
64
            } catch (Error err) {
×
65
                StackTrace.filterStackTrace(err);
×
66
                throw err;
×
67
            }
×
68

69
            throw e;
×
70
        } catch (RuntimeException e) {
×
71
            rollbackForTestClass();
×
72
            StackTrace.filterStackTrace(e);
×
73
            throw e;
×
74
        }
1✔
75
    }
1✔
76

77
    @NonNull
78
    private static Class<?> getActualTestClass(@NonNull Class<?> testClass) {
79
        return testClass.isSynthetic() ? testClass.getSuperclass() : testClass;
1!
80
    }
81

82
    private static void handleSwitchToNewTestClassIfApplicable(@NonNull Class<?> testClass) {
83
        Class<?> currentTestClass = TestRun.getCurrentTestClass();
1✔
84

85
        if (testClass != currentTestClass) {
1✔
86
            if (currentTestClass == null) {
1✔
87
                savePointForTestClass = new SavePoint();
1✔
88
            } else if (!currentTestClass.isAssignableFrom(testClass)) {
1✔
89
                cleanUpMocksFromPreviousTestClass();
1✔
90
                savePointForTestClass = new SavePoint();
1✔
91
            }
92

93
            TestRun.setCurrentTestClass(testClass);
1✔
94
        }
95
    }
1✔
96

97
    public static void cleanUpMocksFromPreviousTestClass() {
98
        cleanUpMocks(true);
1✔
99
    }
1✔
100

101
    protected static void cleanUpMocksFromPreviousTest() {
102
        cleanUpMocks(false);
1✔
103
    }
1✔
104

105
    public static void cleanUpAllMocks() {
106
        cleanUpMocks(true);
1✔
107
        TestRun.getFakeClasses().discardStartupFakes();
1✔
108
    }
1✔
109

110
    private static void cleanUpMocks(boolean forTestClassAsWell) {
111
        discardTestLevelMockedTypes();
1✔
112

113
        if (forTestClassAsWell) {
1✔
114
            rollbackForTestClass();
1✔
115
        }
116

117
        clearFieldTypeRedefinitions();
1✔
118
    }
1✔
119

120
    private static void rollbackForTestClass() {
121
        SavePoint savePoint = savePointForTestClass;
1✔
122

123
        if (savePoint != null) {
1✔
124
            savePoint.rollback();
1✔
125
            savePointForTestClass = null;
1✔
126
        }
127
    }
1✔
128

129
    protected static void clearFieldTypeRedefinitions() {
130
        TypeRedefinitions fieldTypeRedefinitions = TestRun.getFieldTypeRedefinitions();
1✔
131

132
        if (fieldTypeRedefinitions != null) {
1✔
133
            fieldTypeRedefinitions.cleanUp();
1✔
134
            TestRun.setFieldTypeRedefinitions(null);
1✔
135
        }
136
    }
1✔
137

138
    protected static void prepareForNextTest() {
139
        if (savePointForTest == null) {
1✔
140
            savePointForTest = new SavePoint();
1✔
141
        }
142

143
        TestRun.prepareForNextTest();
1✔
144
    }
1✔
145

146
    protected static void discardTestLevelMockedTypes() {
147
        SavePoint savePoint = savePointForTest;
1✔
148

149
        if (savePoint != null) {
1✔
150
            savePoint.rollback();
1✔
151
            savePointForTest = null;
1✔
152
        }
153
    }
1✔
154

155
    protected static void handleMockFieldsForWholeTestClass(@NonNull Object target) {
156
        Class<?> testClass = getActualTestClass(target.getClass());
1✔
157
        FieldTypeRedefinitions fieldTypeRedefinitions = TestRun.getFieldTypeRedefinitions();
1✔
158

159
        if (fieldTypeRedefinitions == null) {
1✔
160
            ParameterNameExtractor.extractNames(testClass);
1✔
161

162
            fieldTypeRedefinitions = new FieldTypeRedefinitions(testClass);
1✔
163
            TestRun.setFieldTypeRedefinitions(fieldTypeRedefinitions);
1✔
164

165
            TestedClassInstantiations testedClassInstantiations = new TestedClassInstantiations();
1✔
166

167
            if (!testedClassInstantiations.findTestedAndInjectableMembers(testClass)) {
1✔
168
                testedClassInstantiations = null;
1✔
169
            }
170

171
            TestRun.setTestedClassInstantiations(testedClassInstantiations);
1✔
172
        }
173

174
        // noinspection ObjectEquality
175
        if (target != TestRun.getCurrentTestInstance()) {
1✔
176
            fieldTypeRedefinitions.assignNewInstancesToMockFields(target);
1✔
177
        }
178
    }
1✔
179

180
    protected static void createInstancesForTestedFieldsFromBaseClasses(@NonNull Object testClassInstance) {
181
        TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
1✔
182

183
        if (testedClasses != null) {
1✔
184
            TestRun.enterNoMockingZone();
1✔
185

186
            try {
187
                testedClasses.assignNewInstancesToTestedFieldsFromBaseClasses(testClassInstance);
1✔
188
            } finally {
189
                TestRun.exitNoMockingZone();
1✔
190
            }
191
        }
192
    }
1✔
193

194
    protected static void createInstancesForTestedFieldsBeforeSetup(@NonNull Object testClassInstance) {
195
        TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
1✔
196

197
        if (testedClasses != null) {
1✔
198
            TestRun.enterNoMockingZone();
1✔
199

200
            try {
201
                testedClasses.assignNewInstancesToTestedFields(testClassInstance, true,
1✔
202
                        Collections.<InjectionProvider> emptyList());
1✔
203
            } finally {
204
                TestRun.exitNoMockingZone();
1✔
205
            }
206
        }
207
    }
1✔
208

209
    protected static void createInstancesForTestedFields(@NonNull Object testClassInstance) {
210
        TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
1✔
211

212
        if (testedClasses != null) {
1✔
213
            List<? extends InjectionProvider> injectableParameters = Collections.emptyList();
1✔
214
            ParameterTypeRedefinitions paramTypeRedefs = TestRun.getExecutingTest().getParameterRedefinitions();
1✔
215

216
            if (paramTypeRedefs != null) {
1✔
217
                injectableParameters = paramTypeRedefs.getInjectableParameters();
1✔
218
            }
219

220
            TestRun.enterNoMockingZone();
1✔
221

222
            try {
223
                testedClasses.assignNewInstancesToTestedFields(testClassInstance, false, injectableParameters);
1✔
224
            } finally {
225
                TestRun.exitNoMockingZone();
1✔
226
            }
227
        }
228
    }
1✔
229

230
    @Nullable
231
    protected static Object[] createInstancesForAnnotatedParameters(@NonNull Object testClassInstance,
232
            @NonNull Method testMethod, @Nullable Object[] parameterValues) {
233
        int numParameters = getParameterCount(testMethod);
1✔
234

235
        if (numParameters == 0) {
1✔
236
            return null;
1✔
237
        }
238

239
        if (parameterValues == null || parameterValues.length != numParameters) {
1!
240
            // noinspection AssignmentToMethodParameter
241
            parameterValues = new Object[numParameters];
1✔
242
        }
243

244
        TestMethod methodInfo = new TestMethod(testMethod, parameterValues);
1✔
245

246
        TestRun.enterNoMockingZone();
1✔
247

248
        try {
249
            ParameterTypeRedefinitions redefinitions = new ParameterTypeRedefinitions(methodInfo, parameterValues);
1✔
250
            TestRun.getExecutingTest().setParameterRedefinitions(redefinitions);
1✔
251

252
            TestedParameters testedParameters = new TestedParameters(methodInfo);
1✔
253
            List<? extends InjectionProvider> injectableParameters = redefinitions.getInjectableParameters();
1✔
254
            testedParameters.createTestedParameters(testClassInstance, injectableParameters);
1✔
255
        } finally {
256
            TestRun.exitNoMockingZone();
1✔
257
        }
258

259
        return parameterValues;
1✔
260
    }
261

262
    protected static void concludeTestMethodExecution(@NonNull SavePoint savePoint, @Nullable Throwable thrownByTest,
263
            boolean thrownAsExpected) throws Throwable {
264
        TestRun.enterNoMockingZone();
1✔
265

266
        Error expectationsFailure = RecordAndReplayExecution.endCurrentReplayIfAny();
1✔
267

268
        try {
269
            clearTestedObjectsIfAny();
1✔
270
        } finally {
271
            savePoint.rollback();
1✔
272
            TestRun.exitNoMockingZone();
1✔
273
        }
274

275
        if (thrownByTest != null) {
1!
UNCOV
276
            if (expectationsFailure == null || !thrownAsExpected || isUnexpectedOrMissingInvocation(thrownByTest)) {
×
UNCOV
277
                throw thrownByTest;
×
278
            }
279

280
            Throwable expectationsFailureCause = expectationsFailure.getCause();
×
281

282
            if (expectationsFailureCause != null) {
×
283
                expectationsFailureCause.initCause(thrownByTest);
×
284
            }
285
        }
286

287
        if (expectationsFailure != null) {
1!
UNCOV
288
            throw expectationsFailure;
×
289
        }
290
    }
1✔
291

292
    protected static void clearTestedObjectsIfAny() {
293
        TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
1✔
294

295
        if (testedClasses != null) {
1✔
296
            testedClasses.clearTestedObjects();
1✔
297
        }
298
    }
1✔
299

300
    protected static void clearTestedObjectsCreatedDuringSetup() {
301
        TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
1✔
302

303
        if (testedClasses != null) {
1✔
304
            testedClasses.clearTestedObjectsCreatedDuringSetup();
1✔
305
        }
306
    }
1✔
307

308
    private static boolean isUnexpectedOrMissingInvocation(@NonNull Throwable error) {
UNCOV
309
        Class<?> errorType = error.getClass();
×
UNCOV
310
        return errorType == UnexpectedInvocation.class || errorType == MissingInvocation.class;
×
311
    }
312
}
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