All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.integration.junit4.internal.JUnit4TestRunnerDecorator Maven / Gradle / Ivy

/*
 * Copyright (c) 2006-2013 Rogério Liesenfeld
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.integration.junit4.internal;

import java.lang.reflect.*;

import org.jetbrains.annotations.*;

import org.junit.*;
import org.junit.runners.Suite.*;
import org.junit.runners.model.*;

import mockit.integration.internal.*;
import mockit.internal.expectations.*;
import mockit.internal.state.*;
import mockit.internal.util.*;

final class JUnit4TestRunnerDecorator extends TestRunnerDecorator
{
   /**
    * A "volatile boolean" is as good as a java.util.concurrent.atomic.AtomicBoolean here,
    * since we only need the basic get/set operations.
    */
   private volatile boolean shouldPrepareForNextTest = true;

   @Nullable
   Object invokeExplosively(@NotNull FrameworkMethod it, @Nullable Object target, Object... params) throws Throwable
   {
      Method method = it.getMethod();
      Class testClass = target == null ? method.getDeclaringClass() : target.getClass();

      handleMockingOutsideTestMethods(it, target, testClass);

      // In case it isn't a test method, but a before/after method:
      if (it.getAnnotation(Test.class) == null) {
         if (shouldPrepareForNextTest && it.getAnnotation(Before.class) != null) {
            prepareForNextTest();
            shouldPrepareForNextTest = false;
         }

         TestRun.setRunningIndividualTest(target);
         TestRun.setSavePointForTestMethod(null);

         try {
            return it.invokeExplosively(target, params);
         }
         catch (Throwable t) {
            RecordAndReplayExecution.endCurrentReplayIfAny();
            StackTrace.filterStackTrace(t);
            throw t;
         }
         finally {
            if (it.getAnnotation(After.class) != null) {
               shouldPrepareForNextTest = true;
            }
         }
      }

      if (shouldPrepareForNextTest) {
         prepareForNextTest();
      }

      shouldPrepareForNextTest = true;
      assert target != null;

      try {
         executeTestMethod(it, target, params);
         return null; // it's a test method, therefore has void return type
      }
      catch (Throwable t) {
         StackTrace.filterStackTrace(t);
         throw t;
      }
      finally {
         TestRun.finishCurrentTestExecution(true);
      }
   }

   private void handleMockingOutsideTestMethods(
      @NotNull FrameworkMethod it, @Nullable Object target, @NotNull Class testClass)
   {
      TestRun.enterNoMockingZone();

      try {
         if (target == null) {
            Class currentTestClass = TestRun.getCurrentTestClass();

            if (currentTestClass != null && testClass.isAssignableFrom(currentTestClass)) {
               if (it.getAnnotation(AfterClass.class) != null) {
                  cleanUpMocksFromPreviousTestClass();
               }
            }
            else if (testClass.isAnnotationPresent(SuiteClasses.class)) {
               setUpClassLevelMocksAndStubs(testClass);
            }
            else if (it.getAnnotation(BeforeClass.class) != null) {
               updateTestClassState(null, testClass);
            }
         }
         else {
            updateTestClassState(target, testClass);
         }
      }
      finally {
         TestRun.exitNoMockingZone();
      }
   }

   private void executeTestMethod(@NotNull FrameworkMethod it, @NotNull Object target, Object... parameters)
      throws Throwable
   {
      SavePoint savePoint = new SavePoint();
      TestRun.setSavePointForTestMethod(savePoint);

      Method testMethod = it.getMethod();
      Throwable testFailure = null;
      boolean testFailureExpected = false;

      try {
         Object[] mockParameters = createInstancesForMockParameters(target, testMethod, parameters, savePoint);
         createInstancesForTestedFields(target);

         TestRun.setRunningIndividualTest(target);
         it.invokeExplosively(target, mockParameters == null ? parameters : mockParameters);
      }
      catch (Throwable thrownByTest) {
         testFailure = thrownByTest;
         Class expectedType = testMethod.getAnnotation(Test.class).expected();
         testFailureExpected = expectedType.isAssignableFrom(thrownByTest.getClass());
      }
      finally {
         concludeTestMethodExecution(savePoint, testFailure, testFailureExpected);
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy