/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.arquillian.extension.junit.bridge.observer; import com.liferay.arquillian.extension.junit.bridge.util.FrameworkMethodComparator; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.jboss.arquillian.core.api.annotation.Observes; import org.jboss.arquillian.core.spi.EventContext; import org.jboss.arquillian.test.spi.TestClass; import org.jboss.arquillian.test.spi.event.suite.Test; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Rule; import org.junit.internal.runners.statements.InvokeMethod; import org.junit.internal.runners.statements.RunAfters; import org.junit.internal.runners.statements.RunBefores; import org.junit.rules.RunRules; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; /** * @author Shuyang Zhou */ public class JUnitBridgeObserver { public void aroundTest(final @Observes EventContext<Test> eventContext) throws Throwable { Test test = eventContext.getEvent(); Statement statement = new InvokeMethod(null, test.getTestInstance()) { @Override public void evaluate() { eventContext.proceed(); } }; TestClass arquillianTestClass = test.getTestClass(); Class<?> clazz = arquillianTestClass.getJavaClass(); org.junit.runners.model.TestClass junitTestClass = new org.junit.runners.model.TestClass(clazz); Object target = test.getTestInstance(); statement = withBefores( statement, Before.class, junitTestClass, target); statement = withAfters(statement, After.class, junitTestClass, target); Method method = test.getTestMethod(); statement = withRules( statement, Rule.class, junitTestClass, target, Description.createTestDescription( clazz, method.getName(), method.getAnnotations())); List<FrameworkMethod> frameworkMethods = new ArrayList<>( junitTestClass.getAnnotatedMethods(org.junit.Test.class)); frameworkMethods.removeAll( junitTestClass.getAnnotatedMethods(Ignore.class)); Collections.sort(frameworkMethods, FrameworkMethodComparator.INSTANCE); FrameworkMethod firstFrameworkMethod = frameworkMethods.get(0); boolean firstMethod = false; if (method.equals(firstFrameworkMethod.getMethod())) { firstMethod = true; statement = withBefores( statement, BeforeClass.class, junitTestClass, null); } FrameworkMethod lastFrameworkMethod = frameworkMethods.get( frameworkMethods.size() - 1); boolean lastMethod = false; if (method.equals(lastFrameworkMethod.getMethod())) { lastMethod = true; statement = withAfters( statement, AfterClass.class, junitTestClass, null); } evaluateWithClassRule( statement, junitTestClass, target, Description.createSuiteDescription(clazz), firstMethod, lastMethod); } protected void evaluateWithClassRule( Statement statement, org.junit.runners.model.TestClass junitTestClass, Object target, Description description, boolean firstMethod, boolean lastMethod) throws Throwable { if (!firstMethod && !lastMethod) { statement.evaluate(); return; } List<TestRule> testRules = junitTestClass.getAnnotatedMethodValues( target, ClassRule.class, TestRule.class); testRules.addAll( junitTestClass.getAnnotatedFieldValues( target, ClassRule.class, TestRule.class)); if (testRules.isEmpty()) { statement.evaluate(); return; } handleClassRules(testRules, firstMethod, lastMethod, true); statement = new RunRules(statement, testRules, description); try { statement.evaluate(); } finally { handleClassRules(testRules, firstMethod, lastMethod, false); } } protected void handleClassRules( List<TestRule> testRules, boolean firstMethod, boolean lastMethod, boolean enable) { for (TestRule testRule : testRules) { Class<?> testRuleClass = testRule.getClass(); if (firstMethod) { try { Method handleBeforeClassMethod = testRuleClass.getMethod( "handleBeforeClass", boolean.class); handleBeforeClassMethod.invoke(testRule, enable); } catch (ReflectiveOperationException roe) { continue; } } if (lastMethod) { try { Method handleAfterClassMethod = testRuleClass.getMethod( "handleAfterClass", boolean.class); handleAfterClassMethod.invoke(testRule, enable); } catch (ReflectiveOperationException roe) { continue; } } } } protected Statement withAfters( Statement statement, Class<? extends Annotation> afterClass, org.junit.runners.model.TestClass junitTestClass, Object target) { List<FrameworkMethod> frameworkMethods = junitTestClass.getAnnotatedMethods(afterClass); if (!frameworkMethods.isEmpty()) { statement = new RunAfters(statement, frameworkMethods, target); } return statement; } protected Statement withBefores( Statement statement, Class<? extends Annotation> beforeClass, org.junit.runners.model.TestClass junitTestClass, Object target) { List<FrameworkMethod> frameworkMethods = junitTestClass.getAnnotatedMethods(beforeClass); if (!frameworkMethods.isEmpty()) { statement = new RunBefores(statement, frameworkMethods, target); } return statement; } protected Statement withRules( Statement statement, Class<? extends Annotation> ruleClass, org.junit.runners.model.TestClass junitTestClass, Object target, Description description) { List<TestRule> testRules = junitTestClass.getAnnotatedMethodValues( target, ruleClass, TestRule.class); testRules.addAll( junitTestClass.getAnnotatedFieldValues( target, ruleClass, TestRule.class)); if (!testRules.isEmpty()) { statement = new RunRules(statement, testRules, description); } return statement; } }