You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@onami.apache.org by er...@apache.org on 2013/03/11 16:12:05 UTC
svn commit: r1455170 - in /incubator/onami/trunk/test/src:
main/java/org/apache/onami/test/OnamiRunner.java
main/java/org/apache/onami/test/OnamiSuite.java
test/java/org/apache/onami/test/OnamiSuiteTest.java
Author: eric
Date: Mon Mar 11 15:12:05 2013
New Revision: 1455170
URL: http://svn.apache.org/r1455170
Log:
[ONAMI-101] Add support for OnamiSuite
Added:
incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java
incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java
Modified:
incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java
Modified: incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java?rev=1455170&r1=1455169&r2=1455170&view=diff
==============================================================================
--- incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java (original)
+++ incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java Mon Mar 11 15:12:05 2013
@@ -46,6 +46,7 @@ import org.apache.onami.test.reflection.
import org.apache.onami.test.reflection.HandleException;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
@@ -170,6 +171,42 @@ public class OnamiRunner
}
/**
+ * OnamiRunner constructor to create the runner needed
+ * by the OnamiSuite class.
+ *
+ * @see org.junit.runner.RunWith
+ * @param suite The suite test case class to run.
+ * @param test The test case class to run.
+ * @throws org.junit.runners.model.InitializationError if any error occurs.
+ */
+ public OnamiRunner( Class<?> suite, Class<?> test )
+ throws InitializationError
+ {
+ super( test );
+
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "Inizializing injector for test class: " + test.getName() );
+ }
+
+ this.allModules = inizializeInjector( suite, test );
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "done..." );
+ }
+ }
+ catch ( Exception e )
+ {
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+ throwables.add( e );
+ throw new InitializationError( throwables );
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public void run( final RunNotifier notifier )
@@ -222,6 +259,7 @@ public class OnamiRunner
* @return The instance of the test case.
* @throws Exception when an error occurs.
*/
+ @Override
protected Object createTest()
throws Exception
{
@@ -244,6 +282,30 @@ public class OnamiRunner
}
/**
+ * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}
+ * and {@ OnamiSuite}.
+ *
+ * @param <T> whatever input type is accepted
+ * @param suite the input suite to be analyzed
+ * @param test the input class has to be analyzed
+ * @return a List of Guice Modules built after input class analysis.
+ * @throws IllegalAccessException when a n error occurs.
+ * @throws InstantiationException when a n error occurs.
+ * @throws HandleException when a n error occurs.
+ */
+ protected <T> List<Module> inizializeInjector( Class<?> suite, Class<T> test)
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ final List<Module> modules = inizializeInjector(test);
+ Module m = visitClass( suite );
+ if ( m != null )
+ {
+ modules.add( m );
+ }
+ return modules;
+ }
+
+ /**
* This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
*
* @param <T> whatever input type is accepted
Added: incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java?rev=1455170&view=auto
==============================================================================
--- incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java (added)
+++ incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java Mon Mar 11 15:12:05 2013
@@ -0,0 +1,452 @@
+package org.apache.onami.test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.onami.test.annotation.GuiceModules;
+import org.apache.onami.test.annotation.GuiceProvidedModules;
+import org.apache.onami.test.annotation.Mock;
+import org.apache.onami.test.annotation.MockFramework;
+import org.apache.onami.test.annotation.MockType;
+import org.apache.onami.test.handler.GuiceInjectableClassHandler;
+import org.apache.onami.test.handler.GuiceModuleHandler;
+import org.apache.onami.test.handler.GuiceProvidedModuleHandler;
+import org.apache.onami.test.handler.MockFrameworkHandler;
+import org.apache.onami.test.handler.MockHandler;
+import org.apache.onami.test.mock.MockEngine;
+import org.apache.onami.test.mock.guice.MockTypeListener;
+import org.apache.onami.test.reflection.ClassVisitor;
+import org.apache.onami.test.reflection.HandleException;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.Suite;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.util.Modules;
+
+/**
+ * <p>
+ * It's a {@link Suite} runner.
+ * </p>
+ * <p>
+ * This class creates a Google Guice {@link Injector} configured by {@link GuiceModules} annotation (only fr modules
+ * with default constructor) and {@link GuiceProvidedModules} annotation and {@link Mock}.
+ * </p>
+ * <p>
+ * <b>Example #1:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiSuite.class )
+ * @GuiceModules( SimpleModule.class )
+ * @SuiteClasses({ .class })
+ * public class AcmeTestCase
+ * {
+ *
+ * @GuiceProvidedModules
+ * static public Module getProperties()
+ * {
+ * ...
+ * return Modules.combine(new ComplexModule( loadProperies() ), ... );
+ * }
+ *
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * <b>Example #2:</b> <br>
+ *
+ * <pre>
+ *
+ * @org.junit.runner.RunWith( OnamiSuite.class )
+ * public class AcmeTestCase
+ * extends com.google.inject.AbstractModule
+ * {
+ *
+ * public void configure()
+ * {
+ * // Configure your proper modules
+ * ...
+ * bind( Service.class ).annotatedWith( TestAnnotation.class ).to( ServiceTestImpl.class );
+ * ...
+ * }
+ *
+ * @Mock
+ * private AnotherService serviceMock;
+ *
+ * @Inject
+ * private Service serviceTest;
+ *
+ * @org.junit.Test
+ * public void test()
+ * {
+ * assertNotNull( serviceMock );
+ * assertNotNull( serviceTest );
+ * }
+ * </pre>
+ *
+ * </p>
+ *
+ * @see GuiceMockModule
+ */
+public class OnamiSuite
+ extends Suite
+{
+
+ private static final Logger LOGGER = Logger.getLogger( OnamiSuite.class.getName() );
+
+ private Injector injector;
+
+ private final List<Module> allModules;
+
+ private final Map<Field, Object> mocked = new HashMap<Field, Object>( 1 );
+
+ private MockType mockFramework = MockType.EASY_MOCK;
+
+ private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError {
+ SuiteClasses annotation= klass.getAnnotation(SuiteClasses.class);
+ if (annotation == null)
+ throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName()));
+ return annotation.value();
+ }
+
+ /**
+ * OnamiRunner constructor to create the core JUnice class.
+ *
+ * @see org.junit.runner.RunWith
+ * @param klass The test case class to run.
+ * @throws org.junit.runners.model.InitializationError if any error occurs.
+ */
+ public OnamiSuite( Class<?> klass, RunnerBuilder builder )
+ throws InitializationError
+ {
+ this(builder, klass, getAnnotatedClasses(klass));
+
+ }
+
+ /**
+ * Called by this class and subclasses once the classes making up the suite have been determined
+ *
+ * @param builder builds runners for classes in the suite
+ * @param klass the root of the suite
+ * @param suiteClasses the classes in the suite
+ * @throws InitializationError
+ */
+ protected OnamiSuite( RunnerBuilder builder, Class<?> suite, Class<?>[] suiteClasses )
+ throws InitializationError
+ {
+ super( suite, runners( suite, suiteClasses ) );
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "Inizializing injector for siote class: " + suite.getName() );
+ }
+
+ this.allModules = inizializeInjector( suite );
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( "done..." );
+ }
+ }
+ catch ( Exception e )
+ {
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+ throwables.add( e );
+ throw new InitializationError( throwables );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run( final RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### Run test case: " + getTestClass().getJavaClass() + " ### " );
+ LOGGER.finer( " #### Creating injector ####" );
+ }
+
+ this.injector = createInjector( allModules );
+ super.run( notifier );
+ this.flush();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ### End test case: " + getTestClass().getJavaClass().getName() + " ### " );
+ }
+ }
+
+ private static List<Runner> runners( Class<?> suite, Class<?>[] children ) throws InitializationError {
+ ArrayList<Runner> runners= new ArrayList<Runner>();
+ for (Class<?> each : children) {
+ Runner childRunner= new OnamiRunner( suite, each );
+ if (childRunner != null)
+ runners.add(childRunner);
+ }
+ return runners;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ private void flush()
+ {
+ this.injector = null;
+ this.allModules.clear();
+ this.mocked.clear();
+ }
+
+ @Override
+ protected void runChild( Runner runner, RunNotifier notifier )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " +++ invoke runner: " + runner + " +++ " );
+ }
+
+ super.runChild( runner, notifier );
+ resetAllResetAfterMocks();
+
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " --- end runner: " + runner + " --- " );
+ }
+ }
+
+ /**
+ * Shortcut to create the Injector given a list of Modules.
+ *
+ * @param modules the list of modules have to be load
+ * @return an Injector instance built using the input Module list
+ */
+ protected Injector createInjector( List<Module> modules )
+ {
+ return Guice.createInjector( modules );
+ }
+
+ /**
+ * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
+ *
+ * @param <T> whatever input type is accepted
+ * @param clazz the input class has to be analyzed
+ * @return a List of Guice Modules built after input class analysis.
+ * @throws IllegalAccessException when a n error occurs.
+ * @throws InstantiationException when a n error occurs.
+ * @throws HandleException when a n error occurs.
+ */
+ protected <T> List<Module> inizializeInjector( Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ final List<Module> modules = new ArrayList<Module>();
+ Module m = visitClass( clazz );
+ if ( m != null )
+ {
+ modules.add( m );
+ }
+ return modules;
+ }
+
+ private void resetAllResetAfterMocks()
+ {
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Mock mockAnnotation = entry.getKey().getAnnotation( Mock.class );
+ if ( mockAnnotation.resetAfter() )
+ {
+ MockEngine mockEngine = MockEngineFactory.getMockEngine( mockFramework );
+ mockEngine.resetMock( entry.getValue() );
+ }
+ }
+ }
+
+ /**
+ * @throws HandleException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ private <T> Module visitClass( final Class<T> clazz )
+ throws HandleException, InstantiationException, IllegalAccessException
+ {
+ try
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " Start introspecting class: " + clazz.getName() );
+ }
+ final List<Module> allModules = new ArrayList<Module>();
+
+ // Setup the handlers
+ final GuiceProvidedModuleHandler guiceProvidedModuleHandler = new GuiceProvidedModuleHandler();
+ final GuiceModuleHandler guiceModuleHandler = new GuiceModuleHandler();
+ final GuiceInjectableClassHandler<Inject> guiceInjectableClassHandler = new GuiceInjectableClassHandler<Inject>();
+ final GuiceInjectableClassHandler<javax.inject.Inject> jsr330InjectableClassHandler = new GuiceInjectableClassHandler<javax.inject.Inject>();
+
+ final MockHandler mockHandler = new MockHandler();
+ final MockFrameworkHandler mockFrameworkHandler = new MockFrameworkHandler();
+
+ // Visit class and super-classes
+ new ClassVisitor()
+ .registerHandler( GuiceProvidedModules.class, guiceProvidedModuleHandler )
+ .registerHandler( GuiceModules.class, guiceModuleHandler )
+ .registerHandler( Mock.class, mockHandler )
+ .registerHandler( MockFramework.class, mockFrameworkHandler )
+ .registerHandler( Inject.class, guiceInjectableClassHandler )
+ .registerHandler( javax.inject.Inject.class, jsr330InjectableClassHandler )
+ .visit( clazz );
+
+ // Retrieve mock framework
+ if ( mockFrameworkHandler.getMockType() != null )
+ {
+ this.mockFramework = mockFrameworkHandler.getMockType();
+ }
+
+ // retrieve the modules founded
+ allModules.addAll( guiceProvidedModuleHandler.getModules() );
+ allModules.addAll( guiceModuleHandler.getModules() );
+ MockEngine engine = MockEngineFactory.getMockEngine( this.mockFramework );
+ this.mocked.putAll( mockHandler.getMockedObject( engine ) );
+ if ( !this.mocked.isEmpty() )
+ {
+ // Replace all real module binding with Mocked moduled.
+ Module m = Modules.override( allModules ).with( new GuiceMockModule( this.mocked ) );
+ allModules.clear();
+ allModules.add( m );
+ }
+
+ // Add only clasess that have got the Inject annotation
+ final Class<?>[] guiceInjectableClasses = guiceInjectableClassHandler.getClasses();
+ final Class<?>[] jsr330InjectableClasses = jsr330InjectableClassHandler.getClasses();
+
+ final AbstractModule statcInjector = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ // inject all STATIC dependencies
+ if ( guiceInjectableClasses.length != 0 )
+ {
+ requestStaticInjection( guiceInjectableClasses );
+ }
+
+ if ( jsr330InjectableClasses.length != 0 )
+ {
+ requestStaticInjection( jsr330InjectableClasses );
+ }
+
+
+ }
+ };
+ if ( guiceInjectableClasses.length != 0 || jsr330InjectableClasses.length != 0 )
+ {
+ allModules.add( statcInjector );
+ }
+
+ // Check if the class is itself a Google Module.
+ if ( Module.class.isAssignableFrom( getTestClass().getJavaClass() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " creating module from test class " + getTestClass().getJavaClass() );
+ }
+ final Module classModule = (Module) getTestClass().getJavaClass().newInstance();
+ allModules.add( classModule );
+ }
+
+ // create MockTypeListenerModule
+ if ( this.mocked.size() != 0 )
+ {
+ final AbstractModule mockTypeListenerModule = new AbstractModule()
+ {
+ @Override
+ protected void configure()
+ {
+ bindListener( Matchers.any(), new MockTypeListener( mocked ) );
+ }
+ };
+
+ // BEGIN patch for issue: google-guice: #452
+ for ( Entry<Field, Object> entry : mocked.entrySet() )
+ {
+ final Field field = entry.getKey();
+ final Object mock = entry.getValue();
+ if ( Modifier.isStatic( field.getModifiers() ) )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " inject static mock field: " + field.getName() );
+ }
+
+ field.setAccessible( true );
+ field.set( field.getDeclaringClass(), mock );
+ }
+ }
+ // END patch for issue: google-guice: #452
+
+ allModules.add( mockTypeListenerModule );
+ }
+
+ if ( allModules.size() != 0 )
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append( " Collected modules: " );
+ builder.append( "\n" );
+ for ( Module module : allModules )
+ {
+ builder.append( " " + module );
+ builder.append( "\n" );
+ }
+ LOGGER.finer( builder.toString() );
+ }
+ return Modules.combine( allModules );
+ }
+ return null;
+ }
+ finally
+ {
+ if ( LOGGER.isLoggable( Level.FINER ) )
+ {
+ LOGGER.finer( " ...done" );
+ }
+ }
+ }
+
+}
Added: incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java
URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java?rev=1455170&view=auto
==============================================================================
--- incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java (added)
+++ incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java Mon Mar 11 15:12:05 2013
@@ -0,0 +1,10 @@
+package org.apache.onami.test;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(OnamiSuite.class)
+@SuiteClasses({ InjectDependingMockObjectTestCase.class, InjectFromSuperClassTestCase.class })
+public class OnamiSuiteTest {
+
+}
Re: svn commit: r1455170 - in /incubator/onami/trunk/test/src:
main/java/org/apache/onami/test/OnamiRunner.java main/java/org/apache/onami/test/OnamiSuite.java
test/java/org/apache/onami/test/OnamiSuiteTest.java
Posted by Simone Tripodi <si...@apache.org>.
SUPER! :)
http://people.apache.org/~simonetripodi/
http://simonetripodi.livejournal.com/
http://twitter.com/simonetripodi
http://www.99soft.org/
On Mon, Mar 11, 2013 at 4:12 PM, <er...@apache.org> wrote:
> Author: eric
> Date: Mon Mar 11 15:12:05 2013
> New Revision: 1455170
>
> URL: http://svn.apache.org/r1455170
> Log:
> [ONAMI-101] Add support for OnamiSuite
>
> Added:
> incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java
> incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java
> Modified:
> incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java
>
> Modified: incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java
> URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java?rev=1455170&r1=1455169&r2=1455170&view=diff
> ==============================================================================
> --- incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java (original)
> +++ incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiRunner.java Mon Mar 11 15:12:05 2013
> @@ -46,6 +46,7 @@ import org.apache.onami.test.reflection.
> import org.apache.onami.test.reflection.HandleException;
> import org.junit.runner.notification.RunNotifier;
> import org.junit.runners.BlockJUnit4ClassRunner;
> +import org.junit.runners.Suite;
> import org.junit.runners.model.FrameworkMethod;
> import org.junit.runners.model.InitializationError;
>
> @@ -170,6 +171,42 @@ public class OnamiRunner
> }
>
> /**
> + * OnamiRunner constructor to create the runner needed
> + * by the OnamiSuite class.
> + *
> + * @see org.junit.runner.RunWith
> + * @param suite The suite test case class to run.
> + * @param test The test case class to run.
> + * @throws org.junit.runners.model.InitializationError if any error occurs.
> + */
> + public OnamiRunner( Class<?> suite, Class<?> test )
> + throws InitializationError
> + {
> + super( test );
> +
> + try
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( "Inizializing injector for test class: " + test.getName() );
> + }
> +
> + this.allModules = inizializeInjector( suite, test );
> +
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( "done..." );
> + }
> + }
> + catch ( Exception e )
> + {
> + final List<Throwable> throwables = new LinkedList<Throwable>();
> + throwables.add( e );
> + throw new InitializationError( throwables );
> + }
> + }
> +
> + /**
> * {@inheritDoc}
> */
> public void run( final RunNotifier notifier )
> @@ -222,6 +259,7 @@ public class OnamiRunner
> * @return The instance of the test case.
> * @throws Exception when an error occurs.
> */
> + @Override
> protected Object createTest()
> throws Exception
> {
> @@ -244,6 +282,30 @@ public class OnamiRunner
> }
>
> /**
> + * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}
> + * and {@ OnamiSuite}.
> + *
> + * @param <T> whatever input type is accepted
> + * @param suite the input suite to be analyzed
> + * @param test the input class has to be analyzed
> + * @return a List of Guice Modules built after input class analysis.
> + * @throws IllegalAccessException when a n error occurs.
> + * @throws InstantiationException when a n error occurs.
> + * @throws HandleException when a n error occurs.
> + */
> + protected <T> List<Module> inizializeInjector( Class<?> suite, Class<T> test)
> + throws HandleException, InstantiationException, IllegalAccessException
> + {
> + final List<Module> modules = inizializeInjector(test);
> + Module m = visitClass( suite );
> + if ( m != null )
> + {
> + modules.add( m );
> + }
> + return modules;
> + }
> +
> + /**
> * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
> *
> * @param <T> whatever input type is accepted
>
> Added: incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java
> URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java?rev=1455170&view=auto
> ==============================================================================
> --- incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java (added)
> +++ incubator/onami/trunk/test/src/main/java/org/apache/onami/test/OnamiSuite.java Mon Mar 11 15:12:05 2013
> @@ -0,0 +1,452 @@
> +package org.apache.onami.test;
> +
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied. See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +
> +import java.lang.reflect.Field;
> +import java.lang.reflect.Modifier;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.LinkedList;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Map.Entry;
> +import java.util.logging.Level;
> +import java.util.logging.Logger;
> +
> +import org.apache.onami.test.annotation.GuiceModules;
> +import org.apache.onami.test.annotation.GuiceProvidedModules;
> +import org.apache.onami.test.annotation.Mock;
> +import org.apache.onami.test.annotation.MockFramework;
> +import org.apache.onami.test.annotation.MockType;
> +import org.apache.onami.test.handler.GuiceInjectableClassHandler;
> +import org.apache.onami.test.handler.GuiceModuleHandler;
> +import org.apache.onami.test.handler.GuiceProvidedModuleHandler;
> +import org.apache.onami.test.handler.MockFrameworkHandler;
> +import org.apache.onami.test.handler.MockHandler;
> +import org.apache.onami.test.mock.MockEngine;
> +import org.apache.onami.test.mock.guice.MockTypeListener;
> +import org.apache.onami.test.reflection.ClassVisitor;
> +import org.apache.onami.test.reflection.HandleException;
> +import org.junit.runner.Runner;
> +import org.junit.runner.notification.RunNotifier;
> +import org.junit.runners.Suite;
> +import org.junit.runners.model.InitializationError;
> +import org.junit.runners.model.RunnerBuilder;
> +
> +import com.google.inject.AbstractModule;
> +import com.google.inject.Guice;
> +import com.google.inject.Inject;
> +import com.google.inject.Injector;
> +import com.google.inject.Module;
> +import com.google.inject.matcher.Matchers;
> +import com.google.inject.util.Modules;
> +
> +/**
> + * <p>
> + * It's a {@link Suite} runner.
> + * </p>
> + * <p>
> + * This class creates a Google Guice {@link Injector} configured by {@link GuiceModules} annotation (only fr modules
> + * with default constructor) and {@link GuiceProvidedModules} annotation and {@link Mock}.
> + * </p>
> + * <p>
> + * <b>Example #1:</b> <br>
> + *
> + * <pre>
> + *
> + * @org.junit.runner.RunWith( OnamiSuite.class )
> + * @GuiceModules( SimpleModule.class )
> + * @SuiteClasses({ .class })
> + * public class AcmeTestCase
> + * {
> + *
> + * @GuiceProvidedModules
> + * static public Module getProperties()
> + * {
> + * ...
> + * return Modules.combine(new ComplexModule( loadProperies() ), ... );
> + * }
> + *
> + * </pre>
> + *
> + * </p>
> + * <p>
> + * <b>Example #2:</b> <br>
> + *
> + * <pre>
> + *
> + * @org.junit.runner.RunWith( OnamiSuite.class )
> + * public class AcmeTestCase
> + * extends com.google.inject.AbstractModule
> + * {
> + *
> + * public void configure()
> + * {
> + * // Configure your proper modules
> + * ...
> + * bind( Service.class ).annotatedWith( TestAnnotation.class ).to( ServiceTestImpl.class );
> + * ...
> + * }
> + *
> + * @Mock
> + * private AnotherService serviceMock;
> + *
> + * @Inject
> + * private Service serviceTest;
> + *
> + * @org.junit.Test
> + * public void test()
> + * {
> + * assertNotNull( serviceMock );
> + * assertNotNull( serviceTest );
> + * }
> + * </pre>
> + *
> + * </p>
> + *
> + * @see GuiceMockModule
> + */
> +public class OnamiSuite
> + extends Suite
> +{
> +
> + private static final Logger LOGGER = Logger.getLogger( OnamiSuite.class.getName() );
> +
> + private Injector injector;
> +
> + private final List<Module> allModules;
> +
> + private final Map<Field, Object> mocked = new HashMap<Field, Object>( 1 );
> +
> + private MockType mockFramework = MockType.EASY_MOCK;
> +
> + private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError {
> + SuiteClasses annotation= klass.getAnnotation(SuiteClasses.class);
> + if (annotation == null)
> + throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName()));
> + return annotation.value();
> + }
> +
> + /**
> + * OnamiRunner constructor to create the core JUnice class.
> + *
> + * @see org.junit.runner.RunWith
> + * @param klass The test case class to run.
> + * @throws org.junit.runners.model.InitializationError if any error occurs.
> + */
> + public OnamiSuite( Class<?> klass, RunnerBuilder builder )
> + throws InitializationError
> + {
> + this(builder, klass, getAnnotatedClasses(klass));
> +
> + }
> +
> + /**
> + * Called by this class and subclasses once the classes making up the suite have been determined
> + *
> + * @param builder builds runners for classes in the suite
> + * @param klass the root of the suite
> + * @param suiteClasses the classes in the suite
> + * @throws InitializationError
> + */
> + protected OnamiSuite( RunnerBuilder builder, Class<?> suite, Class<?>[] suiteClasses )
> + throws InitializationError
> + {
> + super( suite, runners( suite, suiteClasses ) );
> + try
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( "Inizializing injector for siote class: " + suite.getName() );
> + }
> +
> + this.allModules = inizializeInjector( suite );
> +
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( "done..." );
> + }
> + }
> + catch ( Exception e )
> + {
> + final List<Throwable> throwables = new LinkedList<Throwable>();
> + throwables.add( e );
> + throw new InitializationError( throwables );
> + }
> + }
> +
> + /**
> + * {@inheritDoc}
> + */
> + public void run( final RunNotifier notifier )
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " ### Run test case: " + getTestClass().getJavaClass() + " ### " );
> + LOGGER.finer( " #### Creating injector ####" );
> + }
> +
> + this.injector = createInjector( allModules );
> + super.run( notifier );
> + this.flush();
> +
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " ### End test case: " + getTestClass().getJavaClass().getName() + " ### " );
> + }
> + }
> +
> + private static List<Runner> runners( Class<?> suite, Class<?>[] children ) throws InitializationError {
> + ArrayList<Runner> runners= new ArrayList<Runner>();
> + for (Class<?> each : children) {
> + Runner childRunner= new OnamiRunner( suite, each );
> + if (childRunner != null)
> + runners.add(childRunner);
> + }
> + return runners;
> + }
> +
> + /**
> + * {@inheritDoc}
> + */
> + private void flush()
> + {
> + this.injector = null;
> + this.allModules.clear();
> + this.mocked.clear();
> + }
> +
> + @Override
> + protected void runChild( Runner runner, RunNotifier notifier )
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " +++ invoke runner: " + runner + " +++ " );
> + }
> +
> + super.runChild( runner, notifier );
> + resetAllResetAfterMocks();
> +
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " --- end runner: " + runner + " --- " );
> + }
> + }
> +
> + /**
> + * Shortcut to create the Injector given a list of Modules.
> + *
> + * @param modules the list of modules have to be load
> + * @return an Injector instance built using the input Module list
> + */
> + protected Injector createInjector( List<Module> modules )
> + {
> + return Guice.createInjector( modules );
> + }
> +
> + /**
> + * This method collects modules from {@link GuiceModules}, {@link GuiceProvidedModules}, {@link Mock}.
> + *
> + * @param <T> whatever input type is accepted
> + * @param clazz the input class has to be analyzed
> + * @return a List of Guice Modules built after input class analysis.
> + * @throws IllegalAccessException when a n error occurs.
> + * @throws InstantiationException when a n error occurs.
> + * @throws HandleException when a n error occurs.
> + */
> + protected <T> List<Module> inizializeInjector( Class<T> clazz )
> + throws HandleException, InstantiationException, IllegalAccessException
> + {
> + final List<Module> modules = new ArrayList<Module>();
> + Module m = visitClass( clazz );
> + if ( m != null )
> + {
> + modules.add( m );
> + }
> + return modules;
> + }
> +
> + private void resetAllResetAfterMocks()
> + {
> + for ( Entry<Field, Object> entry : mocked.entrySet() )
> + {
> + final Mock mockAnnotation = entry.getKey().getAnnotation( Mock.class );
> + if ( mockAnnotation.resetAfter() )
> + {
> + MockEngine mockEngine = MockEngineFactory.getMockEngine( mockFramework );
> + mockEngine.resetMock( entry.getValue() );
> + }
> + }
> + }
> +
> + /**
> + * @throws HandleException
> + * @throws IllegalAccessException
> + * @throws InstantiationException
> + */
> + private <T> Module visitClass( final Class<T> clazz )
> + throws HandleException, InstantiationException, IllegalAccessException
> + {
> + try
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " Start introspecting class: " + clazz.getName() );
> + }
> + final List<Module> allModules = new ArrayList<Module>();
> +
> + // Setup the handlers
> + final GuiceProvidedModuleHandler guiceProvidedModuleHandler = new GuiceProvidedModuleHandler();
> + final GuiceModuleHandler guiceModuleHandler = new GuiceModuleHandler();
> + final GuiceInjectableClassHandler<Inject> guiceInjectableClassHandler = new GuiceInjectableClassHandler<Inject>();
> + final GuiceInjectableClassHandler<javax.inject.Inject> jsr330InjectableClassHandler = new GuiceInjectableClassHandler<javax.inject.Inject>();
> +
> + final MockHandler mockHandler = new MockHandler();
> + final MockFrameworkHandler mockFrameworkHandler = new MockFrameworkHandler();
> +
> + // Visit class and super-classes
> + new ClassVisitor()
> + .registerHandler( GuiceProvidedModules.class, guiceProvidedModuleHandler )
> + .registerHandler( GuiceModules.class, guiceModuleHandler )
> + .registerHandler( Mock.class, mockHandler )
> + .registerHandler( MockFramework.class, mockFrameworkHandler )
> + .registerHandler( Inject.class, guiceInjectableClassHandler )
> + .registerHandler( javax.inject.Inject.class, jsr330InjectableClassHandler )
> + .visit( clazz );
> +
> + // Retrieve mock framework
> + if ( mockFrameworkHandler.getMockType() != null )
> + {
> + this.mockFramework = mockFrameworkHandler.getMockType();
> + }
> +
> + // retrieve the modules founded
> + allModules.addAll( guiceProvidedModuleHandler.getModules() );
> + allModules.addAll( guiceModuleHandler.getModules() );
> + MockEngine engine = MockEngineFactory.getMockEngine( this.mockFramework );
> + this.mocked.putAll( mockHandler.getMockedObject( engine ) );
> + if ( !this.mocked.isEmpty() )
> + {
> + // Replace all real module binding with Mocked moduled.
> + Module m = Modules.override( allModules ).with( new GuiceMockModule( this.mocked ) );
> + allModules.clear();
> + allModules.add( m );
> + }
> +
> + // Add only clasess that have got the Inject annotation
> + final Class<?>[] guiceInjectableClasses = guiceInjectableClassHandler.getClasses();
> + final Class<?>[] jsr330InjectableClasses = jsr330InjectableClassHandler.getClasses();
> +
> + final AbstractModule statcInjector = new AbstractModule()
> + {
> + @Override
> + protected void configure()
> + {
> + // inject all STATIC dependencies
> + if ( guiceInjectableClasses.length != 0 )
> + {
> + requestStaticInjection( guiceInjectableClasses );
> + }
> +
> + if ( jsr330InjectableClasses.length != 0 )
> + {
> + requestStaticInjection( jsr330InjectableClasses );
> + }
> +
> +
> + }
> + };
> + if ( guiceInjectableClasses.length != 0 || jsr330InjectableClasses.length != 0 )
> + {
> + allModules.add( statcInjector );
> + }
> +
> + // Check if the class is itself a Google Module.
> + if ( Module.class.isAssignableFrom( getTestClass().getJavaClass() ) )
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " creating module from test class " + getTestClass().getJavaClass() );
> + }
> + final Module classModule = (Module) getTestClass().getJavaClass().newInstance();
> + allModules.add( classModule );
> + }
> +
> + // create MockTypeListenerModule
> + if ( this.mocked.size() != 0 )
> + {
> + final AbstractModule mockTypeListenerModule = new AbstractModule()
> + {
> + @Override
> + protected void configure()
> + {
> + bindListener( Matchers.any(), new MockTypeListener( mocked ) );
> + }
> + };
> +
> + // BEGIN patch for issue: google-guice: #452
> + for ( Entry<Field, Object> entry : mocked.entrySet() )
> + {
> + final Field field = entry.getKey();
> + final Object mock = entry.getValue();
> + if ( Modifier.isStatic( field.getModifiers() ) )
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " inject static mock field: " + field.getName() );
> + }
> +
> + field.setAccessible( true );
> + field.set( field.getDeclaringClass(), mock );
> + }
> + }
> + // END patch for issue: google-guice: #452
> +
> + allModules.add( mockTypeListenerModule );
> + }
> +
> + if ( allModules.size() != 0 )
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + StringBuilder builder = new StringBuilder();
> + builder.append( " Collected modules: " );
> + builder.append( "\n" );
> + for ( Module module : allModules )
> + {
> + builder.append( " " + module );
> + builder.append( "\n" );
> + }
> + LOGGER.finer( builder.toString() );
> + }
> + return Modules.combine( allModules );
> + }
> + return null;
> + }
> + finally
> + {
> + if ( LOGGER.isLoggable( Level.FINER ) )
> + {
> + LOGGER.finer( " ...done" );
> + }
> + }
> + }
> +
> +}
>
> Added: incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java
> URL: http://svn.apache.org/viewvc/incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java?rev=1455170&view=auto
> ==============================================================================
> --- incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java (added)
> +++ incubator/onami/trunk/test/src/test/java/org/apache/onami/test/OnamiSuiteTest.java Mon Mar 11 15:12:05 2013
> @@ -0,0 +1,10 @@
> +package org.apache.onami.test;
> +
> +import org.junit.runner.RunWith;
> +import org.junit.runners.Suite.SuiteClasses;
> +
> +@RunWith(OnamiSuite.class)
> +@SuiteClasses({ InjectDependingMockObjectTestCase.class, InjectFromSuperClassTestCase.class })
> +public class OnamiSuiteTest {
> +
> +}
>
>