package org.needle4j.junit;
import java.util.ArrayList;
import java.util.List;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.needle4j.NeedleTestcase;
import org.needle4j.annotation.ObjectUnderTest;
import org.needle4j.injection.InjectionConfiguration;
import org.needle4j.injection.InjectionProvider;
/**
* JUnit {@link MethodRule} for the initialization of the test. The Rule
* processes and initializes all fields annotated with {@link ObjectUnderTest}.
*
* <pre>
* Example:
*
* public class UserDaoBeanTest {
*
* @Rule
* public NeedleRule needle = new NeedleRule();
*
* @ObjectUnderTest
* private UserDaoBean userDao;
*
* @Test
* public void test() {
* ...
* userDao.someAction();
* ...
* }
* }
*
* </pre>
*
* @see NeedleTestcase
*/
public class NeedleRule extends NeedleTestcase implements MethodRule {
private final List<MethodRule> methodRuleChain = new ArrayList<MethodRule>();
public NeedleRule() {
super();
}
/**
* @see NeedleTestcase#NeedleTestcase(InjectionProvider...)
*/
public NeedleRule(final InjectionProvider<?>... injectionProviders) {
super(injectionProviders);
}
NeedleRule(final InjectionConfiguration configuration, final InjectionProvider<?>... injectionProviders) {
super(configuration, injectionProviders);
}
/**
* {@inheritDoc} Before evaluation of the base statement, the test instance
* will initialized.
*/
@Override
public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
Statement appliedStatement = base;
for (MethodRule rule : methodRuleChain) {
appliedStatement = rule.apply(appliedStatement, method, target);
}
return statement(appliedStatement, target);
}
private Statement statement(final Statement base, final Object target) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
initTestcase(target);
base.evaluate();
}
};
}
/**
* Encloses the added rule.
*
* @param rule
* - outer method rule
* @return {@link NeedleRule}
*/
public NeedleRule withOuter(final MethodRule rule) {
if (rule instanceof InjectionProvider) {
addInjectionProvider((InjectionProvider<?>) rule);
}
methodRuleChain.add(0, rule);
return this;
}
}