org.grouplens.common.test.GuiceTestRunner Maven / Gradle / Ivy
/*
* GroupLens Common Utilities
* Copyright © 2011 Regents of the University of Minnesota
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of the University of Minnesota nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software has been partly funded by NSF grant IIS 08-08692.
*/
package org.grouplens.common.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
*
* GuiceTestRunner allows junit tests to have parameterized constructors
* annotated with @Inject, and it allows methods annotated with @Before, @After,
* @BeforeClass, @AfterClass, and @Test to have parameters as well.
*
*
* Note, the methods should not be annotated with @Inject since those methods
* are called by Guice when an instance is constructed. This runner also assumes
* that all parameters can be instantiated by Guice; exceptions will be thrown
* if this is not the case.
*
*
* Use the @TestModule annotation to specify the Module to use when creating the
* Injector.
*
*/
public class GuiceTestRunner extends BlockJUnit4ClassRunner {
private final Class> testClass;
private final Injector injector;
public GuiceTestRunner(Class> klass) throws InitializationError {
super(klass);
this.testClass = klass;
TestModule testModule = klass.getAnnotation(TestModule.class);
if (testModule != null) {
try {
Module m = (Module) testModule.value().newInstance();
this.injector = Guice.createInjector(m);
} catch (Exception e) {
List t = new ArrayList();
t.add(e);
throw new InitializationError(t);
}
} else {
// no TestModule annotation, so use no module
this.injector = Guice.createInjector();
}
}
@Override
protected Object createTest() {
return injector.getInstance(testClass);
}
@Override
protected Statement methodInvoker(FrameworkMethod method, Object test) {
return new InjectInvokeMethod(this, method, test);
}
/** Overridden to return InjectRunAfters instead of RunAfters. */
@Override
protected Statement withBeforeClasses(Statement statement) {
List befores = getTestClass().getAnnotatedMethods(BeforeClass.class);
return new InjectRunBefores(this, statement, befores, null);
}
/** Overridden to return InjectRunAfters instead of RunAfters. */
@Override
protected Statement withAfterClasses(Statement statement) {
List afters = getTestClass().getAnnotatedMethods(AfterClass.class);
return new InjectRunAfters(this, statement, afters, null);
}
/** Overridden to return InjectRunBefores instead of RunBefores. */
@Override
protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
List befores = getTestClass().getAnnotatedMethods(Before.class);
return new InjectRunBefores(this, statement, befores, target);
}
/** Overridden to return InjectRunAfters instead of RunAfters. */
@Override
protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
List afters = getTestClass().getAnnotatedMethods(After.class);
return new InjectRunAfters(this, statement, afters, target);
}
/** This is now somewhat of a misnomer and no longer follows the
* expected contract. It is effectively validatePublicVoid() and
* allows for multiple argument methods. */
@Override
protected void validatePublicVoidNoArgMethods(Class extends Annotation> annotation, boolean isStatic, List errors) {
// copied, and then modified implementation from ParentRunner
List methods = getTestClass().getAnnotatedMethods(annotation);
for (FrameworkMethod eachTestMethod: methods)
eachTestMethod.validatePublicVoid(isStatic, errors); // used to be validatePublicVoidNoArg()
}
@Override
protected void validateZeroArgConstructor(List errors) {
// do nothing, constructor can take any arguments
}
/** This method should be used by Statements that need to
* invoke FrameworkMethods, and use the returned array as
* the parameters to that method. */
public Object[] injectParameters(Method m) {
// FIXME: we should build up the parameters in a safer way
Class>[] parameterTypes = m.getParameterTypes();
Object[] injectedParameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
injectedParameters[i] = injector.getInstance(parameterTypes[i]);
}
return injectedParameters;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy