View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.integration.junit4;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.lang.annotation.Annotation;
12  import java.util.List;
13  
14  import mockit.Expectations;
15  import mockit.Invocation;
16  import mockit.Mock;
17  import mockit.MockUp;
18  import mockit.Tested;
19  import mockit.internal.faking.FakeInvocation;
20  import mockit.internal.util.StackTrace;
21  
22  import org.junit.runners.model.FrameworkMethod;
23  
24  /**
25   * Startup fake that modifies the JUnit 4.5+ test runner so that it calls back to JMockit immediately after every test
26   * executes. When that happens, JMockit will assert any expectations recorded during the test in {@link Expectations}
27   * subclasses.
28   * <p>
29   * This class is not supposed to be accessed from user code. JMockit will automatically load it at startup.
30   */
31  public final class FakeFrameworkMethod extends MockUp<FrameworkMethod> {
32      @NonNull
33      private final JUnit4TestRunnerDecorator decorator = new JUnit4TestRunnerDecorator();
34  
35      @Nullable
36      @Mock
37      public Object invokeExplosively(@NonNull Invocation invocation, Object target, Object... params) throws Throwable {
38          return decorator.invokeExplosively((FakeInvocation) invocation, target, params);
39      }
40  
41      @Mock
42      public static void validatePublicVoidNoArg(@NonNull Invocation invocation, boolean isStatic,
43              List<Throwable> errors) {
44          FrameworkMethod it = invocation.getInvokedInstance();
45          assert it != null;
46  
47          int previousErrorCount = errors.size();
48  
49          if (!isStatic && eachParameterContainsAKnownAnnotation(it.getMethod().getParameterAnnotations())) {
50              it.validatePublicVoid(false, errors);
51          } else {
52              ((FakeInvocation) invocation).prepareToProceedFromNonRecursiveMock();
53              it.validatePublicVoidNoArg(isStatic, errors);
54          }
55  
56          int errorCount = errors.size();
57  
58          for (int i = previousErrorCount; i < errorCount; i++) {
59              Throwable errorAdded = errors.get(i);
60              StackTrace.filterStackTrace(errorAdded);
61          }
62      }
63  
64      private static boolean eachParameterContainsAKnownAnnotation(
65              @NonNull Annotation[][] parametersAndTheirAnnotations) {
66          if (parametersAndTheirAnnotations.length == 0) {
67              return false;
68          }
69  
70          for (Annotation[] parameterAnnotations : parametersAndTheirAnnotations) {
71              if (!containsAKnownAnnotation(parameterAnnotations)) {
72                  return false;
73              }
74          }
75  
76          return true;
77      }
78  
79      private static boolean containsAKnownAnnotation(@NonNull Annotation[] parameterAnnotations) {
80          if (parameterAnnotations.length == 0) {
81              return false;
82          }
83  
84          for (Annotation parameterAnnotation : parameterAnnotations) {
85              Class<? extends Annotation> annotationType = parameterAnnotation.annotationType();
86              String annotationTypeName = annotationType.getName();
87  
88              if ("mockit.Tested mockit.Mocked mockit.Injectable mockit.Capturing".contains(annotationTypeName)
89                      || annotationType.isAnnotationPresent(Tested.class)) {
90                  return true;
91              }
92          }
93  
94          return false;
95      }
96  }