-
-
Save aslakknutsen/3975179 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="UTF-8"?> | |
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian" xsi:schemaLocation="http://jboss.org/schema/arquillian | |
http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> | |
<defaultProtocol type="Servlet 3.0"/> | |
<extension qualifier="suite"> | |
<property name="deploymentClass">org.jboss.arquillian.extension.suite.Deployments</property> | |
</extension> | |
</arquillian> |
package org.jboss.arquillian.extension.suite; | |
import java.util.concurrent.Callable; | |
import org.jboss.arquillian.config.descriptor.api.ArquillianDescriptor; | |
import org.jboss.arquillian.container.spi.Container; | |
import org.jboss.arquillian.container.spi.ContainerRegistry; | |
import org.jboss.arquillian.container.spi.client.container.DeployableContainer; | |
import org.jboss.arquillian.container.spi.client.deployment.Deployment; | |
import org.jboss.arquillian.container.spi.client.deployment.DeploymentScenario; | |
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData; | |
import org.jboss.arquillian.container.spi.event.DeployDeployment; | |
import org.jboss.arquillian.container.spi.event.DeployManagedDeployments; | |
import org.jboss.arquillian.container.spi.event.DeploymentEvent; | |
import org.jboss.arquillian.container.spi.event.UnDeployDeployment; | |
import org.jboss.arquillian.container.spi.event.UnDeployManagedDeployments; | |
import org.jboss.arquillian.container.spi.event.container.AfterStart; | |
import org.jboss.arquillian.container.spi.event.container.BeforeStop; | |
import org.jboss.arquillian.container.test.impl.client.deployment.event.GenerateDeployment; | |
import org.jboss.arquillian.core.api.Event; | |
import org.jboss.arquillian.core.api.Instance; | |
import org.jboss.arquillian.core.api.InstanceProducer; | |
import org.jboss.arquillian.core.api.annotation.Inject; | |
import org.jboss.arquillian.core.api.annotation.Observes; | |
import org.jboss.arquillian.core.api.event.ManagerStarted; | |
import org.jboss.arquillian.core.spi.EventContext; | |
import org.jboss.arquillian.core.spi.LoadableExtension; | |
import org.jboss.arquillian.test.spi.TestClass; | |
import org.jboss.arquillian.test.spi.annotation.ClassScoped; | |
import org.jboss.arquillian.test.spi.annotation.TestScoped; | |
import org.jboss.arquillian.test.spi.context.ClassContext; | |
import org.jboss.arquillian.test.spi.event.suite.Before; | |
import org.jboss.arquillian.test.spi.event.suite.BeforeClass; | |
public class ArquillianSuiteExtension implements LoadableExtension { | |
public void register(ExtensionBuilder builder) { | |
builder.observer(SuiteDeployer.class); | |
} | |
public static class SuiteDeployer { | |
private Class<?> deploymentClass; | |
private DeploymentScenario suiteDeploymentScenario; | |
@Inject | |
@ClassScoped | |
private InstanceProducer<DeploymentScenario> classDeploymentScenario; | |
@Inject | |
private Event<DeploymentEvent> deploymentEvent; | |
@Inject | |
private Event<GenerateDeployment> generateDeploymentEvent; | |
@Inject | |
// Active some form of ClassContext around our deployments due to assumption bug in AS7 extension. | |
private Instance<ClassContext> classContext; | |
private ProtocolMetaData cachedProtocolMetaData; | |
@TestScoped | |
@Inject | |
private InstanceProducer<ProtocolMetaData> testScopedProtocolMetaData; | |
public void startup(@Observes(precedence = -100) ManagerStarted event, ArquillianDescriptor descriptor) { | |
deploymentClass = getDeploymentClass(descriptor); | |
executeInClassScope(new Callable<Void>() { | |
public Void call() throws Exception { | |
generateDeploymentEvent.fire(new GenerateDeployment(new TestClass(deploymentClass))); | |
suiteDeploymentScenario = classDeploymentScenario.get(); | |
return null; | |
} | |
}); | |
} | |
public void deploy(@Observes final AfterStart event, final ContainerRegistry registry) { | |
executeInClassScope(new Callable<Void>() { | |
public Void call() throws Exception { | |
for (Deployment d : suiteDeploymentScenario.deployments()) { | |
deploymentEvent.fire(new DeployDeployment(findContainer(registry, | |
event.getDeployableContainer()), d)); | |
} | |
return null; | |
} | |
}); | |
} | |
public void undeploy(@Observes final BeforeStop event, final ContainerRegistry registry) { | |
executeInClassScope(new Callable<Void>() { | |
public Void call() throws Exception { | |
for (Deployment d : suiteDeploymentScenario.deployments()) { | |
deploymentEvent.fire(new UnDeployDeployment(findContainer(registry, | |
event.getDeployableContainer()), d)); | |
} | |
return null; | |
} | |
}); | |
} | |
public void blockDeployManagedDeployments(@Observes EventContext<DeployManagedDeployments> ignored) { | |
// We need to block DeployManagedDeployments event | |
} | |
public void storeProtocolMetaData(@Observes ProtocolMetaData protocolMetaData) { | |
cachedProtocolMetaData = protocolMetaData; | |
} | |
public void resotreProtocolMetaData(@Observes EventContext<Before> eventContext) { | |
testScopedProtocolMetaData.set(cachedProtocolMetaData); | |
eventContext.proceed(); | |
} | |
public void restoreDeploymentScenario(@Observes EventContext<BeforeClass> event) { | |
// Setup the Suite level scenario as if it came from the TestClass | |
event.proceed(); | |
classDeploymentScenario.set(suiteDeploymentScenario); | |
} | |
public void blockUnDeployManagedDeployments(@Observes EventContext<UnDeployManagedDeployments> ignored) { | |
// We need to block UnDeployManagedDeployments event | |
} | |
private void executeInClassScope(Callable<Void> call) { | |
try { | |
classContext.get().activate(deploymentClass); | |
call.call(); | |
} catch (Exception e) { | |
throw new RuntimeException("Could not invoke operation", e); | |
} finally { | |
classContext.get().deactivate(); | |
} | |
} | |
private Container findContainer(ContainerRegistry registry, DeployableContainer<?> deployable) { | |
for (Container container : registry.getContainers()) { | |
if (container.getDeployableContainer() == deployable) { | |
return container; | |
} | |
} | |
return null; | |
} | |
private Class<?> getDeploymentClass(ArquillianDescriptor descriptor) { | |
if (descriptor == null) { | |
throw new IllegalArgumentException("Descriptor must be specified"); | |
} | |
String className = descriptor.extension("suite").getExtensionProperties().get("deploymentClass"); | |
if (className == null) { | |
throw new IllegalArgumentException( | |
"A extension element with property deploymentClass must be specified in arquillian.xml"); | |
} | |
try { | |
return Class.forName(className); | |
} catch (ClassNotFoundException e) { | |
throw new RuntimeException("Could not load defined deploymentClass: " + className, e); | |
} | |
} | |
} | |
} |
package org.jboss.arquillian.extension.suite; | |
import org.jboss.arquillian.container.test.api.Deployment; | |
import org.jboss.arquillian.extension.suite.tests.Test1; | |
import org.jboss.shrinkwrap.api.ShrinkWrap; | |
import org.jboss.shrinkwrap.api.asset.EmptyAsset; | |
import org.jboss.shrinkwrap.api.spec.WebArchive; | |
public class Deployments { | |
@Deployment | |
public static WebArchive deploy() { | |
return ShrinkWrap.create(WebArchive.class) | |
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") | |
.addPackage(Test1.class.getPackage()); | |
} | |
} |
org.jboss.arquillian.extension.suite.ArquillianSuiteExtension |
package org.jboss.arquillian.extension.suite.tests; | |
import javax.enterprise.inject.spi.BeanManager; | |
import junit.framework.Assert; | |
import org.jboss.arquillian.junit.Arquillian; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
@RunWith(Arquillian.class) | |
public class Test1 { | |
@Test | |
public void shouldInject(BeanManager bm) { | |
System.out.println("Where are We?"); | |
Assert.assertNotNull(bm); | |
} | |
} |
Ok, seems I just need to rename the "LoadableExtension" file as "org.jboss.arquillian.core.spi.LoadableExtension" , and place it under /src/main/resources/META-INF/services ( I'm using a Maven project )... Now the Suite if finally working ...!!! A good installation guide for this Extension would have been very nice .. but anyway, I finally figured it out ... phew !
Hi Aslak,
I've managed to use the brute force suite solution, thank You for your well-done job. Everything works fine while one issue still exists: I see that when using the suite, arquillian deployment algorithm tries to instantiate ALL the singleton classes found on a classpath (WAR provided by the ShrinkWrap as part of @deployment). We have a large-scale project and classpath I'm trying to use is pretty big, but I'm not expecting this kind of eager loading during deployment.
My question is: is it supposed to work this way, or it's just a bug? BTW, when running arquillian tests without suite-extension, I don't see this problem at all, seems like lazy-loading model implemented then, as it supposed to be.
Thanks for your answer in advance.
Welcome,
I am also using DBUnit extension configured as
<extension qualifier="persistence-dbunit">
<property name="datatypeFactory">org.dbunit.ext.h2.H2DataTypeFactory</property>
<property name="excludePoi">true</property>
<property name="caseSensitiveTableNames">false</property>
</extension>
and I am facing problems during test execution:
Caused by: java.lang.NullPointerException
at org.jboss.arquillian.persistence.core.deployment.PersistenceExtensionArchiveAppender.requiredLibraries(PersistenceExtensionArchiveAppender.java:81)
at org.jboss.arquillian.persistence.core.deployment.PersistenceExtensionArchiveAppender.createAuxiliaryArchive(PersistenceExtensionArchiveAppender.java:58)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.loadAuxiliaryArchives(DeploymentGenerator.java:209)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.buildTestableDeployments(DeploymentGenerator.java:160)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.createTestableDeployments(DeploymentGenerator.java:148)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:85)
...
at org.jboss.arquillian.extension.suite.ArquillianSuiteExtension$SuiteDeployer.executeInClassScope
Could you please help me how should I configure my env properly ?
I just created my fork out of ITCrowd one.
I added extra Annotation for selecting global deployment.
Hi Aslak,
if I run this extension with a single test ( for example mvn -Dtest=ATest test) then ARQ undeploy my app automatically. But if I run the suite with mvn test on my project everything works well but ARQ doesn't undeploy my app.
My environment:
ARQ version : 1.1.2.Final
App server: Jboss 7.2.0.Final
Did I miss something with the configuration?
Hello Aslak,
I'm getting the following error while using this extension. I am using TestNG with Arrquillian
Caused by: java.lang.IllegalArgumentException: No active SuiteScoped Context to bind to
at org.jboss.arquillian.core.impl.ManagerImpl.bind(ManagerImpl.java:173)
at org.jboss.arquillian.core.impl.ManagerImpl.bindAndFire(ManagerImpl.java:235)
at org.jboss.arquillian.core.impl.InstanceImpl.set(InstanceImpl.java:74)
at org.jboss.as.arquillian.protocol.jmx.JMXProtocolAS7.getPackager(JMXProtocolAS7.java:45)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.buildTestableDeployments(DeploymentGenerator.java:169)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.createTestableDeployments(DeploymentGenerator.java:148)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
Can you please help, what is it that I am missing. Configured the extension as shown above.
Hello Asalak,
I have injected the suiteContext at the class level
@Inject
private Instance suiteContext;
and activated the contect in the method startup
suiteContext.activate();
With this it started working like a charm.
Thanks,
Krishna.
Hello Asceta,
I use Persistence and DBUnit extension too (defaultDataSource, defaultDataSeedStrategy, datatypeFactory, defaultDataSetLocation, etc) .
I do not find how to configure it integrated with ArquillianSuiteExtension.
Somebody is using it?
Thanks
Pere
Hello Aslak. Does this have to use a war? I want to run tests in Karaf, so I need to deploy bundles.
Mmm... searching in Internet , looks like I may need to re-compile the whole Arquillian project , to get the Suite Extension registered in a file called /META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension ?!?!?
I can see this file inside arquillian-container-impl-base-1.0.3.Final.jar , and arquillian-config-impl-base-1.0.3.Final.jar,
with just one line : org.jboss.arquillian.container.impl.ContainerExtension
Can anyone just post a good documentation on how to get this Suit integrated into JBoss "for dummies" ???
Thanks a lot !!