/**
   * Sets up the mocks defined in the given mock class.
   *
   * <p>If the type {@linkplain MockClass#realClass referred to} by the mock class is actually an
   * interface, then a {@linkplain #newEmptyProxy(ClassLoader, Class) new empty proxy} is created.
   *
   * @param mockClassOrInstance the mock class itself (given by its {@code Class} literal), or an
   *     instance of the mock class
   * @return the new proxy instance created for the mocked interface, or {@code null} otherwise
   * @throws IllegalArgumentException if a given mock class fails to specify the corresponding real
   *     class using the {@code @MockClass(realClass = ...)} annotation; or if a mock class defines
   *     a mock method for which no corresponding real method or constructor exists in the real
   *     class; or if the real method matching a mock method is {@code abstract}
   * @see #setUpMock(Class, Object)
   * @see #setUpMocks(Object...)
   * @see <a
   *     href="http://code.google.com/p/jmockit/source/browse/trunk/main/test/mockit/MockAnnotationsTest.java#696">
   *     Example</a>
   */
  public static <T> T setUpMock(Object mockClassOrInstance) {
    Class<?> mockClass;
    Object mock;

    if (mockClassOrInstance instanceof Class<?>) {
      mockClass = (Class<?>) mockClassOrInstance;
      mock = null;
    } else {
      mockClass = mockClassOrInstance.getClass();
      mock = mockClassOrInstance;
    }

    MockClassSetup setup = new MockClassSetup(mock, mockClass);
    Class<?> realClass = setup.getRealClass();
    T proxy = null;

    if (realClass.isInterface()) {
      //noinspection unchecked
      proxy = (T) newEmptyProxy(mockClass.getClassLoader(), realClass);
      setup.setRealClass(proxy.getClass());
    }

    setup.redefineMethods();

    return proxy;
  }
  /**
   * Given a mix of {@linkplain MockClass mock} and real classes, {@linkplain #setUpMock(Class,
   * Class) sets up} each mock class for the associated real class, and {@linkplain #stubOut stubs
   * out} each specified regular class.
   *
   * @param mockAndRealClasses one or more mock classes and/or regular classes to be stubbed out
   */
  public static void setUpMocksAndStubs(Class<?>... mockAndRealClasses) {
    for (Class<?> mockOrRealClass : mockAndRealClasses) {
      MockClass metadata = mockOrRealClass.getAnnotation(MockClass.class);

      if (metadata != null) {
        new MockClassSetup(mockOrRealClass, metadata).redefineMethods();
      } else {
        new ClassStubbing(mockOrRealClass).stubOut();
      }
    }
  }
 /**
  * Same as {@link #newEmptyProxy(ClassLoader, Class)}, but with the class loader obtained from the
  * interface to be proxied. Note that this may lead to a {@code NoClassDefFoundError} if that
  * interface was loaded by the boot class loader (usually, when it's a JRE class). Therefore, you
  * should only use this method for application-defined interfaces.
  *
  * <p>This method is just a convenience for some uses of the <em>Mockups</em> API. In <em>JMockit
  * Expectations</em> in particular, mocked instances will be automatically created and assigned to
  * any mock fields or parameters.
  *
  * @see <a
  *     href="http://code.google.com/p/jmockit/source/browse/trunk/main/test/integrationTests/textFile/TextFileUsingAnnotatedMockClassesTest.java#91">
  *     Example</a>
  */
 public static <E> E newEmptyProxy(Class<E> interfaceToBeProxied) {
   return newEmptyProxy(interfaceToBeProxied.getClassLoader(), interfaceToBeProxied);
 }