| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // 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.apache.cloudstack.test.utils; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.springframework.context.annotation.Bean; |
| import org.springframework.context.annotation.ComponentScan; |
| |
| import com.cloud.utils.component.ComponentContext; |
| import com.cloud.utils.component.ComponentInstantiationPostProcessor; |
| import com.cloud.utils.component.ComponentMethodInterceptor; |
| import com.cloud.utils.db.TransactionContextBuilder; |
| import com.cloud.utils.exception.CloudRuntimeException; |
| |
| public class SpringUtils { |
| |
| /** |
| * This method allows you to use @ComponentScan for your unit testing but |
| * it limits the scope of the classes found to the class specified in |
| * the @ComponentScan annotation. |
| * |
| * Without using this method, the default behavior of @ComponentScan is |
| * to actually scan in the package of the class specified rather than |
| * only the class. This can cause extra classes to be loaded which causes |
| * the classes these extra classes depend on to be loaded. The end effect |
| * is often most of the project gets loaded. |
| * |
| * In order to use this method properly, you must do the following: <li> |
| * - Specify @ComponentScan with basePackageClasses, includeFilters, and |
| * useDefaultFilters=true. See the following example. |
| * |
| * <pre> |
| * @ComponentScan(basePackageClasses={AffinityGroupServiceImpl.class, EventUtils.class}, |
| * includeFilters={@Filter(value=TestConfiguration.Library.class, type=FilterType.CUSTOM)}, |
| * useDefaultFilters=false) |
| * </pre> |
| * |
| * - Create a Library class and use that to call this method. See the |
| * following example. The Library class you define here is the Library |
| * class being added in the filter above. |
| * |
| * <pre> |
| * public static class Library implements TypeFilter { |
| * @Override |
| * public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { |
| * ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); |
| * return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); |
| * } |
| * } |
| * </pre> |
| * |
| * @param clazzName name of the class that should be included in the Spring components |
| * @param cs ComponentScan annotation that was declared on the configuration |
| * |
| * @return |
| */ |
| public static boolean includedInBasePackageClasses(String clazzName, ComponentScan cs) { |
| Class<?> clazzToCheck; |
| try { |
| clazzToCheck = Class.forName(clazzName); |
| } catch (ClassNotFoundException e) { |
| throw new CloudRuntimeException("Unable to find " + clazzName); |
| } |
| Class<?>[] clazzes = cs.basePackageClasses(); |
| for (Class<?> clazz : clazzes) { |
| if (clazzToCheck.isAssignableFrom(clazz)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static class CloudStackTestConfiguration { |
| |
| @Bean |
| public ComponentContext componentContext() { |
| return new ComponentContext(); |
| } |
| |
| @Bean |
| public TransactionContextBuilder transactionContextBuilder() { |
| return new TransactionContextBuilder(); |
| } |
| |
| @Bean |
| public ComponentInstantiationPostProcessor instantiatePostProcessor() { |
| ComponentInstantiationPostProcessor processor = new ComponentInstantiationPostProcessor(); |
| |
| List<ComponentMethodInterceptor> interceptors = new ArrayList<ComponentMethodInterceptor>(); |
| interceptors.add(new TransactionContextBuilder()); |
| processor.setInterceptors(interceptors); |
| |
| return processor; |
| } |
| |
| } |
| } |