package org.jboss.arquillian.drone.impl; import java.lang.reflect.Method; import org.jboss.arquillian.container.spi.event.container.AfterDeploy; import org.jboss.arquillian.container.spi.event.container.BeforeUnDeploy; import org.jboss.arquillian.container.test.api.OperateOnDeployment; import org.jboss.arquillian.core.api.annotation.ApplicationScoped; import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.drone.impl.mockdrone.MockDrone; import org.jboss.arquillian.drone.spi.DroneContext; import org.jboss.arquillian.drone.spi.DronePoint; import org.jboss.arquillian.test.spi.TestClass; import org.jboss.arquillian.test.spi.context.ClassContext; import org.jboss.arquillian.test.spi.context.TestContext; import org.jboss.arquillian.test.spi.event.suite.After; import org.jboss.arquillian.test.spi.event.suite.AfterClass; import org.jboss.arquillian.test.spi.event.suite.BeforeClass; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; /** * A test case for testing a proper enrichment of deployment-scoped drone points. */ public class DeploymentTestCase extends EnricherTestCase { /** * A complex test method for testing a proper enrichment of deployment-scoped drone points used in a combination * with manual deployment * * @throws Exception * When anything bad happens */ @Test public void testClassWithManualDeployment() throws Exception { getManager().getContext(ClassContext.class).activate(ManualDeploymentClass.class); Object instance = new ManualDeploymentClass(); mockTestClass(ManualDeploymentClass.class); getManager().getContext(TestContext.class).activate(instance); DroneContext context = fireAndVerifyBeforeSuiteProcess(); fire(new BeforeClass(MethodEnrichedClass.class)); DronePoint<MockDrone> dronePoint1 = new DronePointImpl<MockDrone>(MockDrone.class, DronePoint.Lifecycle.DEPLOYMENT, AnnotationMocks.drone(), AnnotationMocks.operateOnDeployment1()); DronePoint<MockDrone> dronePoint2 = new DronePointImpl<MockDrone>(MockDrone.class, DronePoint.Lifecycle.DEPLOYMENT, AnnotationMocks.drone(), AnnotationMocks.operateOnDeployment2()); runDeploymentTestMethod(dronePoint1, dronePoint2, false, false, false, false, instance, context, "testBeforeDeployment"); runFailingTestMethod(instance, "testShouldFailDeployment1NotDeployed", MockDrone.class); runDeploymentTestMethod(dronePoint1, dronePoint2, false, false, true, false, instance, context, "testDeploy1"); runFailingTestMethod(instance, "testShouldFailDeployment2NotDeployed", MockDrone.class); runDeploymentTestMethod(dronePoint1, dronePoint2, true, false, true, true, instance, context, "testDeploy2Deployed1", MockDrone.class); runDeploymentTestMethod(dronePoint1, dronePoint2, true, true, true, true, instance, context, "testDeployed12", MockDrone.class, MockDrone.class); runDeploymentTestMethod(dronePoint1, dronePoint2, true, true, false, true, instance, context, "testDestroy1Deployed2", MockDrone.class, MockDrone.class); runFailingTestMethod(instance, "testShouldFailDeployment1Destroyed", MockDrone.class); runDeploymentTestMethod(dronePoint1, dronePoint2, false, true, false, false, instance, context, "testDestroy2Destroyed1", MockDrone.class); runFailingTestMethod(instance, "testShouldFailDeployment2Destroyed", MockDrone.class); fire(new AfterClass(ManualDeploymentClass.class)); } /** * Runs a test method of the {@link ManualDeploymentClass} class that should fail with ISE with the message * containing: "has deployment lifecycle" * * @param classInstance * an instance of the {@link ManualDeploymentClass} class * @param testMethodName * the test method to be run * @param params * parameters of the test method (if any) * * @throws Exception * When anything bad happens */ private void runFailingTestMethod(Object classInstance, String testMethodName, Class<MockDrone>... params) throws Exception { Method testMethodBeforeDeployment = ManualDeploymentClass.class.getMethod(testMethodName, params); try { enrichClassAndResolveMethod(classInstance, testMethodBeforeDeployment); } catch (IllegalStateException ise) { if (ise.getMessage().contains("has deployment lifecycle")) { return; } } Assert.fail("The test method " + testMethodName + " should have thrown the IllegalStateException containing word: \"has deployment lifecycle\""); } /** * Runs a test method of the {@link ManualDeploymentClass} class and check if the given {@link DronePoint}s are * instantiated or not * * @param dronePoint1 * a drone point tied to {@link AnnotationMocks.DEPLOYMENT_1} deployment to be verified * @param dronePoint2 * a drone point tied to {@link AnnotationMocks.DEPLOYMENT_2} deployment to be verified * @param before1 * whether the {@code dronePoint1} should be instantiated before the test run * @param before2 * whether the {@code dronePoint2} should be instantiated before the test run * @param after1 * whether the {@code dronePoint1} should be instantiated after the test run * @param after2 * whether the {@code dronePoint2} should be instantiated after the test run * @param classInstance * an instance of the {@link ManualDeploymentClass} class * @param context * a drone context the given {@link DronePoint}s should belong to * @param testMethodName * the test method to be run * @param params * parameters of the test method (if any) * * @throws Exception * When anything bad happens */ private void runDeploymentTestMethod(DronePoint<MockDrone> dronePoint1, DronePoint<MockDrone> dronePoint2, boolean before1, boolean before2, boolean after1, boolean after2, Object classInstance, DroneContext context, String testMethodName, Class<MockDrone>... params) throws Exception { Method testMethodBeforeDeployment = ManualDeploymentClass.class.getMethod(testMethodName, params); Object[] parameters = enrichClassAndResolveMethod(classInstance, testMethodBeforeDeployment); verifyDronePointInstantiated(before1, context, dronePoint1); verifyDronePointInstantiated(before2, context, dronePoint2); testMethodBeforeDeployment.invoke(classInstance, parameters); verifyDronePointInstantiated(after1, context, dronePoint1, before1 && !after1); verifyDronePointInstantiated(after2, context, dronePoint2, before1 && !after1); fire(new After(classInstance, testMethodBeforeDeployment)); } /** * Mocks a {@link TestClass} to return the given class when the method {@link TestClass#getJavaClass()} is called. * The mocked test class will be also injectable inside of the Drone implementation. * * @param classToReturn * class to be returned */ private void mockTestClass(final Class<?> classToReturn) { TestClass testClassMock = Mockito.mock(TestClass.class); Mockito.when(testClassMock.getJavaClass()).thenAnswer(new Answer<Class<?>>() { @Override public Class<?> answer(InvocationOnMock invocation) throws Throwable { return classToReturn; } }); bind(ApplicationScoped.class, TestClass.class, testClassMock); } class ManualDeploymentClass { @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone deploymentDrone1; @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone deploymentDrone2; public void testBeforeDeployment() { assertMockDrone1(false); assertMockDrone2(false); } public void testShouldFailDeployment1NotDeployed( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone paramDeplDrone1) { } public void testDeploy1() { assertMockDrone1(false); assertMockDrone2(false); fire(new AfterDeploy(deployableContainer, deploymentDescription1)); assertMockDrone1(true); assertMockDrone2(false); } public void testShouldFailDeployment2NotDeployed( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone paramDeplDrone2) { } public void testDeploy2Deployed1( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone paramDeplDrone1) { assertMockDrone1(true); assertMockDrone2(false); assertMockDrone(true, paramDeplDrone1, AnnotationMocks.DEPLOYMENT_1); fire(new AfterDeploy(deployableContainer, deploymentDescription2)); assertMockDrone1(true); assertMockDrone2(true); assertMockDrone(true, paramDeplDrone1, AnnotationMocks.DEPLOYMENT_1); } public void testDeployed12( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone paramDeplDrone1, @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone paramDeplDrone2) { assertMockDrone1(true); assertMockDrone2(true); assertMockDrone(true, paramDeplDrone1, AnnotationMocks.DEPLOYMENT_1); assertMockDrone(true, paramDeplDrone2, AnnotationMocks.DEPLOYMENT_2); } public void testDestroy1Deployed2( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone paramDeplDrone1, @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone paramDeplDrone2) { assertMockDrone1(true); assertMockDrone2(true); assertMockDrone(true, paramDeplDrone1, AnnotationMocks.DEPLOYMENT_1); assertMockDrone(true, paramDeplDrone2, AnnotationMocks.DEPLOYMENT_2); fire(new BeforeUnDeploy(deployableContainer, deploymentDescription1)); } public void testShouldFailDeployment1Destroyed( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_1) MockDrone paramDeplDrone1) { } public void testDestroy2Destroyed1( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone paramDeplDrone2) { assertMockDrone1(true); assertMockDrone2(true); assertMockDrone(true, paramDeplDrone2, AnnotationMocks.DEPLOYMENT_2); fire(new BeforeUnDeploy(deployableContainer, deploymentDescription2)); } public void testShouldFailDeployment2Destroyed( @Drone @OperateOnDeployment(AnnotationMocks.DEPLOYMENT_2) MockDrone paramDeplDrone2) { } private void assertMockDrone1(boolean shouldExist) { assertMockDrone(shouldExist, deploymentDrone1, AnnotationMocks.DEPLOYMENT_1); } private void assertMockDrone2(boolean shouldExist) { assertMockDrone(shouldExist, deploymentDrone2, AnnotationMocks.DEPLOYMENT_2); } private void assertMockDrone(boolean shouldExist, MockDrone mockDrone, String deploymentName) { if (shouldExist) { Assert.assertNotNull( "Mock drone instance tied to " + deploymentName + " should NOT be null", mockDrone); } else { Assert.assertNull( "Mock drone instance tied to " + deploymentName + " should be null", mockDrone); } } } }