/**
 * Copyright (c) 2009 by Alistair A. Israel
 *
 * This software is made available under the terms of the MIT License.
 *
 * Created May 29, 2009
 */
package dirty.mockito;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.junit.Rule;

import dirty.mockito.junit.interceptors.ActiveTestInterceptor;

/**
 * <p>
 * JUnit 4 test parameterized base class that performs instantiation, mocking
 * and injection of mocks. Uses an internal {@link ActiveTestInterceptor} to
 * perform mocking of elements annotated with <a href=
 * "http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mock.html"
 * ><code>&#064;Mock</code></a> then inject those mocks into fields (in the
 * object under test) annotated with <code>&#064;Autowired</code>.
 * </p>
 * <p>
 * Suppose we have a JPA DAO class, that depends upon an
 * <code>&#064;Autowired</code> <code>EntityManager</code>:
 * </p>
 *
 * <pre>
 * public class WidgetDao {
 *     &#064;Autowired
 *     private EntityManager em;
 *
 *     public Widget find(final Long id) {
 *         return em.find(Widget.class, id);
 *     }
 * }
 * </pre>
 * <p>
 * Now, to write a unit test for <code>WidgetDao</code> using
 * <code>ActiveTest</code>, we simply extend
 * <code>ActiveTest&lt;WidgetDao&gt;</code>, declare a field of type
 * <code>WidgetDao</code>, declare another field of type
 * <code>Entitymanager</code> and annotate that using <code>&#064;Mock</code>.
 *
 * <pre>
 * public class WidgetDaoTest extends ActiveTest&lt;WidgetDao&gt; {
 *   private WidgetDao widgetDao;
 *
 *   &#064;Mock
 *   private EntityManager em;
 *
 *   &#064;Test
 *   public void testFind() {
 *     widgetDao.find(123L);
 *     Mockito.verify(em).find(Entity.class, 123L);
 *   }
 * }
 * </pre>
 * <p>
 * That's it. ActiveTest takes care of creating the mocks for fields annotated
 * <code>&#064;Mock</code>, instantiating the class under test (
 * <code>WidgetDao</code>), and injecting the mock objects into
 * <code>&#064;Autowired</code> fields.
 * </p>
 * <p>
 * Because Spring itself is used to inject <code>&#064;Autowired</code>
 * dependencies, <code>ActiveTest</code> supports field, setter and
 * constructor-based injection.
 * </p>
 *
 * @param <T>
 *            the type of the class to instantiate and inject mocks into
 * @author Alistair A. Israel
 * @see <a href="http://code.google.com/p/dirty-mockito/" target="_blan
 *      >dirty-mockito</a>
 * @see <a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/Autowired.html"
 *      target="_blank>&#064;Autowired</a>
 * @see <a href=
 *      "http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mock.html"
 *      target="_blank>&#064;Mock</a>
 * @since 0.1
 */
public class ActiveTest<T> {

    /**
     * The {@link ActiveTestInterceptor} that does all the mojo.
     */
    @Rule
    // CHECKSTYLE:OFF
    public final ActiveTestInterceptor<T> activeTestInterceptor;
    // CHECKSTYLE:ON

    /**
     *
     */
    public ActiveTest() {
        final Class<T> classUnderTest = determineTypeParameter();
        this.activeTestInterceptor = ActiveTestInterceptor.thatWorksOn(classUnderTest);
    }

    /**
     * @return the Type parameter to our generic base class
     */
    @SuppressWarnings("unchecked")
    private Class<T> determineTypeParameter() {
        Class<?> specificClass = this.getClass();
        Type genericSuperclass = specificClass.getGenericSuperclass();
        while (!(genericSuperclass instanceof ParameterizedType)
                && specificClass != MagicTest.class) {
            specificClass = specificClass.getSuperclass();
            genericSuperclass = specificClass.getGenericSuperclass();
        }
        final ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;

        final Type firstTypeParameter = parameterizedType.getActualTypeArguments()[0];
        return (Class<T>) firstTypeParameter;
    }
}

@@ -263,19 +263,21 @@
 g.junit.
-Rul
+Befor
 e;%0A%0Aimpo
@@ -1533,24 +1533,26 @@
 &gt; %7B%0A *   
+  
 private Widg
@@ -1566,27 +1566,26 @@
 idgetDao;%0A *
-%0A *
+  
    &#064;Moc
@@ -1591,16 +1591,18 @@
 ck%0A *   
+ 
+ 
 private 
@@ -1627,16 +1627,18 @@
  *%0A *   
+  
 &#064;Te
@@ -1642,16 +1642,18 @@
 ;Test%0A *
+  
    publi
@@ -1679,16 +1679,20 @@
 %0A *     
+    
 widgetDa
@@ -1703,24 +1703,28 @@
 nd(123L);%0A *
+    
      Mockito
@@ -1763,16 +1763,18 @@
 23L);%0A *
+  
    %7D%0A * 
@@ -2262,20 +2262,16 @@
         
-    
 the type
@@ -2903,46 +2903,15 @@
     
-@Rule%0A    // CHECKSTYLE:OFF%0A    public
+private
  fin
@@ -2964,29 +2964,8 @@
 tor;
-%0A    // CHECKSTYLE:ON
 %0A%0A  
@@ -3135,16 +3135,33 @@
 erceptor
+%0A                
 .thatWor
@@ -3877,16 +3877,33 @@
 izedType
+%0A                
 .getActu
@@ -3975,11 +3975,293 @@
 r;%0A    %7D
+%0A%0A    /**%0A     * For now, we do it this way. When JUnit %3E= 4.7.1 comes out, we can fully%0A     * make use of ActiveTestInterceptor as a proper interceptor. Currently, running%0A     */%0A    @Before%0A    public final void initMocks() %7B%0A        activeTestInterceptor.initMocks(this);%0A    %7D
 %0A%7D%0A

Make ActiveTest still delegate to an ActiveTestInterceptor (for now), but not as a @Rule. Change it back when JUnit > 4.7