Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.
*/
package org.jboss.arquillian.junit;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jboss.arquillian.impl.DeployableTestBuilder;
import org.jboss.arquillian.spi.LifecycleMethodExecutor;
import org.jboss.arquillian.spi.TestMethodExecutor;
import org.jboss.arquillian.spi.TestResult;
import org.jboss.arquillian.spi.TestRunnerAdaptor;
import org.junit.internal.runners.model.MultipleFailureException;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
/**
* Arquillian
*
* @author Aslak Knutsen
* @version $Revision: $
*/
public class Arquillian extends BlockJUnit4ClassRunner
{
/*
* @HACK
* JUnit Hack:
* In JUnit a Exception is thrown and verified/swallowed if @Test(expected) is set. We need to transfer this
* Exception back to the client so the client side can throw it again. This to avoid a incontainer working but failing
* on client side due to no Exception thrown.
*/
// Cleaned up in JUnitTestRunner
public static ThreadLocal caughtTestException = new ThreadLocal();
/*
* @HACK
* Eclipse hack:
* When running multiple TestCases, Eclipse will create a new runner for each of them.
* This results in that AfterSuite is call pr TestCase, but BeforeSuite only on the first created instance.
* A instance of all TestCases are created before the first one is started, so we keep track of which one
* was the last one created. The last one created is the only one allowed to call AfterSuite.
*/
private static ThreadLocal lastCreatedRunner = new ThreadLocal();
private static ThreadLocal deployableTest = new ThreadLocal();
public Arquillian(Class> klass) throws InitializationError
{
super(klass);
try
{
// first time we're being initialized
if(deployableTest.get() == null)
{
// no, initialization has been attempted before, refuse to do anything else
if(lastCreatedRunner.get() != null)
{
throw new RuntimeException("Arquillian has previously been attempted initialized, but failed. See previous exceptions for cause.");
}
TestRunnerAdaptor adaptor = DeployableTestBuilder.build();
try
{
// don't set it if beforeSuite fails
adaptor.beforeSuite();
deployableTest.set(adaptor);
}
catch (Exception e)
{
throw new InitializationError(Arrays.asList((Throwable)e));
}
}
}
finally
{
lastCreatedRunner.set(this);
}
}
@Override
public void run(RunNotifier notifier)
{
notifier.addListener(new RunListener()
{
@Override
public void testRunFinished(Result result) throws Exception
{
try
{
if(deployableTest.get() != null && lastCreatedRunner.get() == Arquillian.this)
{
deployableTest.get().afterSuite();
deployableTest.get().shutdown();
lastCreatedRunner.set(null);
lastCreatedRunner.remove();
deployableTest.set(null);
deployableTest.remove();
}
}
catch (Exception e)
{
throw new RuntimeException("Could not run @AfterSuite", e);
}
}
});
super.run(notifier);
}
@Override
// TODO: exclude @Integration test classes
protected List computeTestMethods()
{
return super.computeTestMethods();
}
/**
* Override to allow test methods with arguments
*/
@Override
protected void validatePublicVoidNoArgMethods(Class extends Annotation> annotation, boolean isStatic, List errors)
{
List methods = getTestClass().getAnnotatedMethods(annotation);
for (FrameworkMethod eachTestMethod : methods)
{
eachTestMethod.validatePublicVoid(isStatic, errors);
}
}
/*
* Override BeforeClass/AfterClass and Before/After handling.
*
* Let super create the Before/After chain against a EmptyStatement so our newly created Statement
* only contains the method that are of interest to us(@Before..etc).
* They can then optionally be executed if we get expected callback.
*
*/
@Override
protected Statement withBeforeClasses(final Statement originalStatement)
{
final Statement onlyBefores = super.withBeforeClasses(new EmptyStatement());
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
deployableTest.get().beforeClass(
Arquillian.this.getTestClass().getJavaClass(),
new StatementLifecycleExecutor(onlyBefores));
originalStatement.evaluate();
}
};
}
@Override
protected Statement withAfterClasses(final Statement originalStatement)
{
final Statement onlyAfters = super.withAfterClasses(new EmptyStatement());
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
multiExecute
(
originalStatement,
new Statement() { @Override public void evaluate() throws Throwable
{
deployableTest.get().afterClass(
Arquillian.this.getTestClass().getJavaClass(),
new StatementLifecycleExecutor(onlyAfters));
}}
);
}
};
}
@Override
protected Statement withBefores(final FrameworkMethod method, final Object target, final Statement originalStatement)
{
final Statement onlyBefores = super.withBefores(method, target, new EmptyStatement());
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
deployableTest.get().before(
target,
method.getMethod(),
new StatementLifecycleExecutor(onlyBefores));
originalStatement.evaluate();
}
};
}
@Override
protected Statement withAfters(final FrameworkMethod method, final Object target, final Statement originalStatement)
{
final Statement onlyAfters = super.withAfters(method, target, new EmptyStatement());
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
multiExecute
(
originalStatement,
new Statement() { @Override public void evaluate() throws Throwable
{
deployableTest.get().after(
target,
method.getMethod(),
new StatementLifecycleExecutor(onlyAfters));
}}
);
}
};
}
@Override
protected Statement methodInvoker(final FrameworkMethod method, final Object test)
{
return new Statement()
{
@Override
public void evaluate() throws Throwable
{
TestResult result = deployableTest.get().test(new TestMethodExecutor()
{
@Override
public void invoke(Object... parameters) throws Throwable
{
try
{
//Object parameterValues = TestEnrichers.enrich(deployableTest.get().getActiveContext(), getMethod());
method.invokeExplosively(test, parameters); //, (Object[])parameterValues);
}
catch (Throwable e)
{
// Force a way to return the thrown Exception from the Container the client.
caughtTestException.set(e);
throw e;
}
}
public Method getMethod()
{
return method.getMethod();
}
public Object getInstance()
{
return test;
}
});
if(result.getThrowable() != null)
{
throw result.getThrowable();
}
}
};
}
/**
* A helper to safely execute multiple statements in one.
*
* Will execute all statements even if they fail, all exceptions will be kept. If multiple {@link Statement}s
* fail, a {@link MultipleFailureException} will be thrown.
*
* @author Aslak Knutsen
* @version $Revision: $
*/
private void multiExecute(Statement... statements) throws Throwable
{
List exceptions = new ArrayList();
for(Statement command : statements)
{
try
{
command.evaluate();
}
catch (Exception e)
{
exceptions.add(e);
}
}
if(exceptions.isEmpty())
{
return;
}
if(exceptions.size() == 1)
{
throw exceptions.get(0);
}
throw new MultipleFailureException(exceptions);
}
private static class EmptyStatement extends Statement
{
@Override
public void evaluate() throws Throwable
{
}
}
private static class StatementLifecycleExecutor implements LifecycleMethodExecutor
{
private Statement statement;
public StatementLifecycleExecutor(Statement statement)
{
this.statement = statement;
}
public void invoke() throws Throwable
{
statement.evaluate();
}
}
}