/* * JBoss, Home of Professional Open Source * Copyright 2009 Red Hat Inc. and/or its affiliates and other 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.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Logger; import org.jboss.arquillian.core.api.Event; import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.core.api.annotation.Observes; import org.jboss.arquillian.core.spi.ServiceLoader; import org.jboss.arquillian.junit.event.BeforeRules; import org.jboss.arquillian.junit.event.RulesEnrichment; import org.jboss.arquillian.test.spi.TestEnricher; import org.jboss.arquillian.test.spi.event.enrichment.AfterEnrichment; import org.jboss.arquillian.test.spi.event.enrichment.BeforeEnrichment; import org.jboss.arquillian.test.spi.event.enrichment.EnrichmentEvent; import org.junit.Rule; import org.junit.rules.MethodRule; import org.junit.rules.RunRules; import org.junit.rules.TestRule; /** * Enriches instance of the Rule that has been applied; of the Statement that is about to be taken; and of the Test that * is * about to be executed<br/> * * @author <a href="mailto:mjobanek@redhat.com">Matous Jobanek</a> * @version $Revision: $ */ public class RulesEnricher { private static Logger log = Logger.getLogger(RulesEnricher.class.getName()); @Inject private Instance<ServiceLoader> serviceLoader; @Inject private Event<EnrichmentEvent> enrichmentEvent; public void enrichRulesAndTestInstance(@Observes RulesEnrichment event) throws Exception { Object testInstance = event.getTestInstance(); List<Object> toEnrich = getRuleInstances(testInstance); if (toEnrich == null) { return; } toEnrich.add(testInstance); enrichInstances(toEnrich); } public void enrichStatement(@Observes BeforeRules event) throws Exception { List<Object> toEnrich = new ArrayList<Object>(); if (RunRules.class.isInstance(event.getStatementInstance())) { toEnrich.add(SecurityActions.getField(RunRules.class, "statement").get(event.getStatementInstance())); } else { toEnrich.add(event.getStatementInstance()); } enrichInstances(toEnrich); } public void enrichInstances(List<Object> toEnrich) { Collection<TestEnricher> testEnrichers = serviceLoader.get().all(TestEnricher.class); for (Object instance : toEnrich) { enrichmentEvent.fire(new BeforeEnrichment(instance)); for (TestEnricher enricher : testEnrichers) { enricher.enrich(instance); } enrichmentEvent.fire(new AfterEnrichment(instance)); } } /** * Retrieves instances of the TestRule and MethodRule classes */ private List<Object> getRuleInstances(Object testInstance) throws Exception { List<Object> ruleInstances = new ArrayList<Object>(); List<Field> fieldsWithRuleAnnotation = SecurityActions.getFieldsWithAnnotation(testInstance.getClass(), Rule.class); if (fieldsWithRuleAnnotation.isEmpty()) { List<Method> methodsWithAnnotation = SecurityActions.getMethodsWithAnnotation(testInstance.getClass(), Rule.class); if (methodsWithAnnotation.isEmpty()) { // there isn't any rule in the test class return null; } else { log.warning("Please note that methods annotated with @Rule are not fully supported in Arquillian. " + "Specifically, if you want to enrich a field in your Rule implementation class."); return ruleInstances; } } else { for (Field field : fieldsWithRuleAnnotation) { Object fieldInstance = field.get(testInstance); if (isRule(fieldInstance)) { ruleInstances.add(fieldInstance); } } } return ruleInstances; } /** * Decides whether the instance is a Rule or not */ private boolean isRule(Object instance) { return MethodRule.class.isInstance(instance) || TestRule.class.isInstance(instance); } }